I explain:
I would like to know how I can pass method or functions as arguments.
For example, in Python will be:
from MyFile import MyClass
MyClass().my_method_click(function) # without parentheses
In this example, in Python you send the functions or method without
parentheses, if I do:
from MyFile import MyClass
MyClass().my_method_click(function()) # with parentheses
I call the function but don't send it.
In Ruby, when you call a method or function, you can do it with or
without parentheses.
if I do this in Ruby:
require_relative "MyClass"
MyClass.new.my_method_click(function) # without parentheses
Just call it without send it.
Of course, is for a Button, that when I click it, run this operation.
How I can do it in Ruby??
Thanks!
Basically, you want to pass a runnable block of code. I haven't looked into Python yet, but I am sure it supports closures as well.
Anyhow, in Ruby, a "general" way of passing a runnable code is to use blocks (lambdas and procs).
function = lambda { # your code }
MyClass.new.my_method_click(function)
# or a shorter way
MyClass.new.my_method_click(-> { # your code })
# to run a block
def my_method_click(&block)
#you can either `yield` from your receiving method
yield
# or call `.call` method on your lambda/proc instance
block.call
end
You can also get an instance of your class' method or create a new method one using Method.new. But, you'd end up dealing with bindings and binding to the correct instance types, etc. So, it's much easier with Lambdas and Procs.
Related
For example...
There are several methods that I'd like to treat as 'events', and fire my own functions once they've been called.
I do not manually invoke these.
As someone that's not well-versed with Python, but familiar with C#, I'd ideally like to be able patch into a module method, and either alter functionality, or just callback my own methods.
edit: example added
def my_own_callback_method():
# do something here
# imagine in a large code base there's a method I'd like to target and fire my own callback ...
#
# ... something else invokes a method ('not_my_method') in a third-party module ('core').
def not_my_method():
# the orginial function executes as it would
#
# but I'd like to pre/post callback my own method from my module
my_own_callback_method()
Alternatively, it'd be nice to be able to 'patch' a method and alter its functionality. Example below -
# again, imagine in a large code base there's a method I'd like to target ...
# ... but I'd like to alter the way this method works in my own module.
#
# kind of like...
def my_method(something:str, something_else:int):
# my own method patch of how the original 'not_my_method' should work
def not_my_method(something:str, something_else:int):
return my_method(something, something_else)
If you don't have any control over not_my_method's code it will be (almost?) impossible since you want to actually change its source code.
I believe that the best you can achieve is wrapping it in your own function that calls my_method after it calls not_my_method, but that would be pretty much it.
Perhaps you are looking at it from the wrong angle. It might be easier to patch the actual event that calls not_my_method than patching not_my_method itself.
I'm just starting to learn Python and I have the following problem.
Using a package with method "bind", the following code works:
def callback(data):
print data
channel.bind(callback)
but when I try to wrap this inside a class:
class myclass:
def callback(data):
print data
def register_callback:
channel.bind(self.callback)
the call_back method is never called. I tried both "self.callback" and just "callback". Any ideas?
It is not clear to me how your code works, as (1) you did not post the implementation of channel.bind, and (2) your second example is incorrect in the definition of register_callback (it is using a self argument that is not part of the list of parameters of the method, and it lacks parentheses).
Nevertheless, remember that methods usually require a "self" parameter, which is implicitly passed every time you run self.function(), as this is converted internally to a function call with self as its first parameter: function(self, ...). Since your callback has just one argument data, this is probably the problem.
You cannot declare a method bind that is able to accept either a function or a class method (the same problem happens with every OOP language I know: C++, Pascal...).
There are many ways to do this, but, again, without a self-contained example that can be compiled, it is difficult to give suggestions.
You need to pass the self object as well:
def register_callback(self):
channel.bind(self.callback)
What you're doing is entirely possible, but I'm not sure exactly what your issue is, because your sample code as posted is not even syntactically valid. (The second method has no argument list whatsoever.)
Regardless, you might find the following sample code helpful:
def send_data(callback):
callback('my_data')
def callback(data):
print 'Free function callback called with data:', data
# The follwing prints "Free function callback called with data: my_data"
send_data(callback)
class ClassWithCallback(object):
def callback(self, data):
print 'Object method callback called with data:', data
def apply_callback(self):
send_data(self.callback)
# The following prints "Object method callback called with data: my_data"
ClassWithCallback().apply_callback()
# Indeed, the following does the same
send_data(ClassWithCallback().callback)
In Python it is possible to use free functions (callback in the example above) or bound methods (self.callback in the example above) in more or less the same situations, at least for simple tasks like the one you've outlined.
I have created the following constructor:
class Analysis:
def __init__(self, file_list, tot_col, tot_rows):
self.file_list = file_list
self.tot_col = tot_col
self.tot_rows = tot_rows
I then have the method full_analysis() call calc_total_rows() from the same file:
def full_analysis(self):
"""Currently runs all the analysis methods"""
print('Analysing file...\n' +
'----------------------------\n')
calc_total_rows()
From another file I am calling the full_analysis() however errors occur saying that calc_total_rows() is not defined, and the method is just below it.
I'm inexperienced with Python however I tried to rearrange the code and add 'self' in various places to no avail.
The other file does meet the requirements of the constructor, and if I remove the calc_total_rows() method, the print line runs. I however do not wish to call each method individually, and would like to call a single method which runs them all.
If calc_total_rows is an instance method as your question implies, then you need to call self.calc_total_rows() from within full_analysis. Unlike some other languages, Python does not have implicit instance references within method scope; you have to explicitly retrieve the member method from self.
I wish I had found this sooner.
In order to solve this, I had to use self in front of the method.
In my example:
def full_analysis(self):
"""Currently runs all the analysis methods"""
print('Analysing file...\n' +
'----------------------------\n')
self.calc_total_rows()
This works.
I am using a block like this:
def served(fn) :
def wrapper(*args, **kwargs):
p = xmlrpclib.ServerProxy(SERVER, allow_none=True )
return (p.__getattr__(fn.__name__)(*args, **kwargs)) # do the function call
return functools.update_wrapper(wrapper,fn)
#served
def remote_function(a, b):
pass
to wrap a series of XML-RPC calls into a python module. The "served" decorator gets called on stub functions to expose operations on a remote server.
I'm creating stubs like this with the intention of being able to inspect them later for information about the function, specifically its arguments.
As listed, the code above does not transfer argument information from the original function to the wrapper. If I inspect with inspect.getargspec( remote_function ) then I get essentially an empty list, instead of args=['a','b'] that I was expecting.
I'm guessing I need to give additional direction to the functools.update_wrapper() call via the optional assigned parameter, but I'm not sure exactly what to add to that tuple to get the effect I want.
The name and the docstring are correctly transferred to the new function object, but can someone advise me on how to transfer argument definitions?
Thanks.
Previous questions here and here suggest that the decorator module can do this.
I have a situation where I am attempting to port some big, complex python routines to a threaded environment.
I want to be able to, on a per-call basis, redirect the output from the function's print statement somewhere else (a logging.Logger to be specific).
I really don't want to modify the source for the code I am compiling, because I need to maintain backwards compatibility with other software that calls these modules (which is single threaded, and captures output by simply grabbing everything written to sys.stdout).
I know the best option is to do some rewriting, but I really don't have a choice here.
Edit -
Alternatively, is there any way I can override the local definition of print to point to a different function?
I could then define the local print = system print unless overwritten by a kwarg, and would only involve modify a few lines at the beginning of each routine.
In Python2.6 (and 2.7), you can use
from __future__ import print_function
Then you can change the code to use the print() function as you would for Python3
This allows you to create a module global or local function called print which will be used in preference to the builtin function
eg.
from __future__ import print_function
def f(x, print=print):
print(x*x)
f(5)
L=[]
f(6, print=L.append)
print(L)
Modifying the source code doesn't need to imply breaking backward compatibility.
What you need to do is first replace every print statement with a call to a function that does the same thing:
import sys
def _print(*args, **kw):
sep = kw.get('sep', ' ')
end = kw.get('end', '\n')
file = kw.get('file', sys.stdout)
file.write(sep.join(args))
file.write(end)
def foo():
# print "whatever","you","want"
_print("whatever","you","want")
Then the second step is to stop using the _print function directly and make it a keyword argument:
def foo(_print=_print):
...
and make sure to change all internal function calls to pass the _print function around.
Now all the existing code will continue to work and will use print, but you can pass in whatever _print function you want.
Note that the signature of _print is exactly that of the print function in more recent versions of Python, so as soon as you upgrade you can just change it to use print(). Also you may get away with using 2to3 to migrate the print statements in the existing code which should reduce the editing required.
Someone in the sixties had an idea about how to solve this but it requires a bit of alien technology. Unfortunately python has no "current environment" concept and this means you cannot provide context unless specifying it in calls as a parameter.
For handling just this specific problem what about replacing stdout with a file-like object that behaves depending on a thread-specific context ? This way the source code remains the same but for example you can get a separate log for each thread. It's even easy to do this on a specific per-call way... for example:
class MyFakeStdout:
def write(self, s):
try:
separate_logs[current_thread()].write(s)
except KeyError:
old_stdout.write(s)
and then having a function to set a logger locally to a call (with)
PS: I saw the "without touching stdout" in the title but I thought this was because you wanted only some thread to be affected. Touching it while still allowing other threads to work unaffected seems to me compatible with the question.