How to pass an argument to an event handler in wxPython?
Here's my code:
def close_handler(event):
baz(foo)
...
foo = 'bar'
frame.Bind(wx.EVT_CLOSE, close_handler)
How to pass foo to close_handler() function?
import functools
def close_handler(event, foo):
baz(foo)
foo = 'bar'
func = functools.partial(close_handler, foo=foo)
frame.Bind(wx.EVT_CLOSE, func)
Or to conserve some space:
import functools
def close_handler(event, foo):
baz(foo)
frame.Bind(wx.EVT_CLOSE, functools.partial(close_handler, foo='bar'))
Have close_handler create a second event-handling function that uses foo:
def close_handler(foo):
return lambda event: baz(foo)
foo = 'bar'
frame.Bind(wx.EVT_CLOSE, close_handler(foo))
Here lambda event: baz(foo) is an anonymous function that calls baz(foo), silently discarding the event argument. Or you could pass it to baz if you wanted: lambda event: baz(foo, event).
You could also write this without using lambda like so:
def close_handler(foo):
def event_handler(event):
return baz(foo)
return event_handler
Related
It seems like for a vast majority of methods that take blocks, if you have a block, proc, or lambda stored in a variable you can pass it in. For example
mapper = -> (foo) { foo * foo }
(1..5).map(&mapper) # => [1, 4, 9, 16, 25]
The method Class::new can be initialized using a block to create a class, as such:
klass = Class.new do
def foo
'bar'
end
end
klass.new.foo # => "bar"
However, I cannot do something like this
class_body = lambda do
def foo
'bar'
end
end
klass = Class.new(&class_body)
I get ArgumentError (wrong number of arguments (given 1, expected 0)). There is a way around this by doing something like this,
klass = Class.new { class_body.call }
klass.new.foo
But it seems like this shouldn't be necessary. Is there a more idiomatic way to instantiate a class with a block as an argument other than something like
def define_class(&class_body)
Class.new { class_body.call }
end
As both the documentation of Class::new and the error message clearly show, the block is passed one argument [bold emphasis mine]:
new(super_class=Object) { |mod| ... } → a_class
[…]
If a block is given, it is passed the class object, and the block is evaluated in the context of this class like class_eval.
Also, in the error message you posted:
ArgumentError (wrong number of arguments (given 1, expected 0))
The error message is saying that your lambda was passed one argument, but it is expecting none.
The fix is easy: add a parameter to your lambda:
class_body = -> * do
def foo
'bar'
end
end
klass = Class.new(&class_body)
Or, if you don't absolutely require a lambda, you could use a non-lambda Proc:
class_body = proc do
def foo
'bar'
end
end
klass = Class.new(&class_body)
I'd like to get control (to execute some pre-emptive tasks) when a function is called in Python without modifying the source program, e.g., when calling test()
def test(i : int, s: str) -> int:
pass
I'd like a function myobserver to be called, and have some way to inspect (maybe even modify?!) the parameters? Think of it sorta like a mini-debugger, e.g., to add logging to an existing program that can't/shouldn't be modified?
def myobserver(handle)
name = get_name(handle)
for n, arg in enumerate(get_arg_iterator(handle)):
print("Argument {n} of function {name}: {arg}")
ETA: I am not looking for the traditional decorator, because adding a decorator requires changing the source code. (In this sense, decorators are nicer than adding a print, but still similar because they require changes to source.)
Your are looking for python decorators:
from functools import wraps
def debugger(func):
#wraps(func)
def with_logging(*args, **kwargs):
print('"'+func.__name__+'({},{})"'.format(*args, **kwargs)+" was invoked")
# -------------------
# Your logic here
# -------------------
return func(*args, **kwargs)
return with_logging
#debugger
def test(i : int, s: str) -> int:
print('We are in test', i, s)
test(10, 'hello')
EDIT
Since the decorator method mentioned above interferes with the source code (have to apply the # decorators), I propose the following:
# This is source code to observe, should not be _touched_!
class SourceCode:
def __init__(self, label):
self.label = label
def test1(self, i, s):
print('For object labeled {}, we are in {} with param {}, {}'.format(self.label, 'test1', i, s))
def test2(self, k):
print('For object labeled {}, we are in {} with param {}'.format(self.label, 'test2', k))
What I propose is perform some manual effort in writing the hooks, I am not sure if this is feasible (just occured to me, hence adding):
from functools import wraps
# the following is pretty much syntactic and generic
def hook(exist_func, debugger):
#wraps(exist_func)
def run(*args, **kwargs):
return debugger(exist_func, *args, **kwargs)
return run
# here goes your debugger
def myobserver(orig_func, *args, **kwargs):
# -----------------------
# Your logic goes here
# -----------------------
print('Inside my debugger')
return orig_func(*args, **kwargs)
# ---------------------------------
obj = SourceCode('Test')
# making the wrapper ready to receive
no_iterference_hook1 = hook(obj.test1, myobserver)
no_iterference_hook2 = hook(obj.test2, myobserver)
# call your debugger on the function of your choice
no_iterference_hook1(10, 'hello')
no_iterference_hook2('Another')
Sample code:
class Foo
def initialize(abc)
#abc = abc
#bind = bar
end
def bar
SomeClass.new(#abc)
end
end
Now I want to stub bar using rspec and custom stub:
allow('Foo').to receive(:bar).and_return(FakeBar.new)
The issue is that the FakeBar.new has to be initialize with the same arguments :bar receives. Is it possible to get a copy of params passed to :bar at the time we are stubbing and reuse them in the stub class?
Not sure why you want to do what you're doing (probably there is a simpler way), but for what it's worth:
allow("Foo").to receive(:bar) { |arg1, arg2| FakeBar.new(arg1, arg2) }
RSpec docs, block stub implementation
In python, it's fairly straightforward to reference a function:
>>> def foo():
... print "foo called"
... return 1
...
>>> x = foo
>>> foo()
foo called
1
>>> x()
foo called
1
>>> x
<function foo at 0x1004ba5f0>
>>> foo
<function foo at 0x1004ba5f0>
However, it seems to be different in Ruby since a naked foo actually calls foo:
ruby-1.9.2-p0 > def foo
ruby-1.9.2-p0 ?> print "foo called"
ruby-1.9.2-p0 ?> 1
ruby-1.9.2-p0 ?> end
=> nil
ruby-1.9.2-p0 > x = foo
foo called => 1
ruby-1.9.2-p0 > foo
foo called => 1
ruby-1.9.2-p0 > x
=> 1
How do I actually assign the function foo to x and then call it? Or is there a more idiomatic way to do this?
Ruby doesn't have functions. It only has methods (which aren't first-class) and Procs which are first-class, but are not associated with any object.
So, this is a method:
def foo(bar) puts bar end
foo('Hello')
# Hello
Oh, and, yes, this is a real method, not a top-level function or procedure or something. Methods defined at the top-level end up as private(!) instance methods in the Object class:
Object.private_instance_methods(false) # => [:foo]
This is a Proc:
foo = -> bar { puts bar }
foo.('Hello')
# Hello
Notice that Procs are called differently from methods:
foo('Hello') # method
foo.('Hello') # Proc
The foo.(bar) syntax is just syntactic sugar for foo.call(bar) (which for Procs and Methods is also aliased to foo[bar]). Implementing a call method on your object and then calling it with .() is the closest thing you will get to Python's __call__ables.
Note that an important distinction between Ruby Procs and Python lambdas is that there are no restrictions: in Python, a lambda can only contain a single statement, but Ruby doesn't have the distinction between statements and expressions (everything is an expression), and so this limitation simply doesn't exist, therefore in a lot of cases where you need to pass a named function as an argument in Python because you cannot express the logic in a single statement, you would in Ruby simply pass a Proc or a block instead, so that the problem of the ugly syntax for referencing methods doesn't even arise.
You can wrap a method in a Method object (which essentially duck-types Proc) by calling the Object#method method on an object (which will give you a Method whose self is bound to that particular object):
foo_bound = method(:foo)
foo_bound.('Hello')
# Hello
You can also use one of the methods in the Module#instance_method family to get an UnboundMethod from a module (or class, obviously, since a class is-a module), which you can then UnboundMethod#bind to a particular object and call. (I think Python has the same concepts, albeit with a different implementation: an unbound method simply takes the self argument explicitly, just like the way it is declared.)
foo_unbound = Object.instance_method(:foo) # this is an UnboundMethod
foo_unbound.('Hello')
# NoMethodError: undefined method `call' for #<UnboundMethod: Object#foo>
foo_rebound = foo_unbound.bind(self) # this is a Method
foo_rebound.('Hello')
# Hello
Note that you can only bind an UnboundMethod to an object which is an instance of the module you took the method from. You cannot use UnboundMethods to "transplant" behavior between unrelated modules:
bar = module Foo; def bar; puts 'Bye' end; self end.instance_method(:bar)
module Foo; def bar; puts 'Hello' end end
obj = Object.new
bar.bind(obj)
# TypeError: bind argument must be an instance of Foo
obj.extend(Foo)
bar.bind(obj).()
# Bye
obj.bar
# Hello
Note, however, that both the Method and the UnboundMethod are wrappers around the method, not the method itself. Methods are not objects in Ruby. (Contrary to what I have written in other answers, BTW. I really need to go back and fix those.) You can wrap them in objects, but they aren't objects, and you can see that because you essentially get all the same problems you always get with wrappers: identity and state. If you call method multiple times for the same method, you will get a different Method object every time. If you try to store some state on that Method object (such as Python-style __doc__strings, for example), that state will be private to that particular instance, and if you try to retrieve your docstring again via method, you will find that it is gone.
There is also syntactic sugar in the form of the method reference operator .::
bound_method = obj.:foo
Which is identical to
bound_method = obj.method(:foo)
You can use the method instance method inherited from Object to retrieve a Method object, which essentially is a Proc object which you can invoke call on.
In the console, you'd do this:
fooMethod = self.method(:foo) #fooMethod is a Method object
fooMethod.call #invokes fooMethod
Ruby supports proc and lambda which in other languages might be called anonymous functions or closures, depending on how they are used. They might be closer to what you are looking for.
The (main) difference between functions and methods as copied from https://stackoverflow.com/a/26620095/226255
Functions are defined outside of classes, while methods are defined
inside of and part of classes.
Ruby does not have functions and your def foo ends up being a method for the Object class.
If you insist on defining foo like you're doing above, you can extract its "functionality" by doing this:
def foo(a,b)
a+b
end
x = method(:foo).to_proc
x.call(1,2)
=> 3
Explanation:
> method(:foo) # this is Object.method(:foo), returns a Method object bound to
# object of type 'Class(Object)'
=> #<Method: Class(Object)#foo>
method(:foo).to_proc
# a Proc that can be called without the original object the method was bound to
=> #<Proc:0x007f97845f35e8 (lambda)>
Important note:
to_proc "copies" the method's object's associated instance variables if any. Consider this:
class Person
def initialize(name)
#name = name
end
def greet
puts "hello #{#name}"
end
end
greet = Person.new('Abdo').method(:greet)
# note that Person.method(:greet) returns an UnboundMethod and cannot be called
# unless you bind it to an object
> greet.call
hello Abdo
=> nil
Conceptually, if you want a "function" that would work on a certain type of objects, it should be a method and you should organize your code as such. If you only need your "function" in a certain context and wish to pass it around, use lambdas:
greet = lambda { |person| "hello #{person}" }
yell_at = lambda { |person| "HELLO #{person.upcase}" }
def do_to_person(person, m)
m.call(person)
end
do_to_person('Abdo', greet)
When using Proc#call to call a lambda function in Ruby, self always ends up with the value that it had when the function was defined, rather than the value it has when the function is called, for example:
$p = lambda { self }
class Dummy
def test
$p.call
end
end
d = Dummy.new
> d.test
=> main
Calling test returns main, when what I intended it to return is #<Dummy:0xf794> - an instance of Dummy, which was the value of self at the point in the code where I called $p.
In Javascript, I would just pass the object that I want to be the "callee" as the first argument to call. Is there any such functionality in Ruby, allowing me to set an arbitrary object, or at least the current value of self, as the new value for self when I call a Proc?
You're looking for instance_eval, which evaluates a lambda in the context of the calling object.
>> $p = proc { self }
=> #<Proc:0x95cece4#(irb):1 (lambda)>
>> class Dummy
>> def test
>> $p.call
>> end
>>
>> def test1
>> instance_eval(&$p)
>> end
>> end
>> d = Dummy.new
=> #<Dummy:0x946f7c8>
>> d.test
=> main
>> d.test1
=> #<Dummy:0x946f7c8>
You may want to use instance_exec because it allows you to pass arguments to the block whereas instance_eval does not.
def eval_my_proc_with_args(*args, &block)
instance_exec(*args, &block)
end
lambda defines a closure which means it will encapsulate the environment it had when it was defined. If you want self to be the caller just define a regular method or better yet use a block.