python pass self to referenced function - python

I have a function reference that is being called by an object. What I'd like is for that object to pass itself as a parameter to the function as it would normally do for its own functions.
IE I would like to use self.myFoo() instead of self.myFoo(self) in the following sample
Code Sample:
def foo(self):
print(self.toString())
class Node:
def __init__(self, myFoo):
self.myFoo = myFoo
def run(self):
self.myFoo()
def toString(self):
return "Hello World"
n = Node(foo)
n.run()

The problem is that you assigned myFoo to an unbound function and are calling it as though it were bound. If you want to be able to use self.myFoo() you will need to curry the object into the first arg yourself.
from functools import partial
def foo(self):
print(self.toString())
class Node:
def __init__(self, myFoo):
self.myFoo = partial(myFoo, self)
def run(self):
self.myFoo()
def toString(self):
return "Hello World"
n = Node(foo)
n.run()
Alternatively you could use
self.myFoo = types.MethodType(myFoo, self)
in your __init__(self, myFoo) method, but using partial is more commonly done, and more versatile since you can use it to curry arguments for any sort of function, not just methods.

This thread looks like what you are looking for. To bound a method to an object (but not its class) at runtime you can do:
import types
n.foo = types.MethodType(foo, n)

foo is a simple function. To make it callable via self.myFoo() you can attach it to the class - not the object. Even Node.myFoo is still an unbound function you can call it via self.myFoo() within your class.
def __init__(self, myFoo):
Node.myFoo = myFoo

Related

Python - Class object as function argument: Object only - Class not in argument

I am trying to write a function taking a string as an argument and using this argument as a class object.
Note that my explanantion might be strangely formulated sice I could not find an answer online. The MWE below should clarify what I mean, the problematic line is indicated.
Edit: in the MWE, "print" is an example. I need to be able to call the object to update it, print it or, in the case of a list, append to it. I need access to the object itself, not the value of the object.
MWE
# Create a class
class myClass():
def __init__(self):
self.one = "Test"
self.two = "Plop"
# Define function
def myFunction (parameter):
print(myObject.parameter)##### This line is currently not possible.
# Use class
myObject = myClass()
# Use function
myFunction("one")
I am not trying to append a new object to the class, only to call an existing object.
Is this even possible?
Looks like you need the built-in function called getattr
my_object = myClass()
def my_function(parameter):
print(getattr(my_object, parameter, None))
also this is not the best practice to call objects from outer scope like that. i'd suggest to use dict magic methods:
class MyClass:
def __init__(self):
self.one = "Test"
self.two = "Plop"
def __getitem__(self, parameter):
return getattr(self, parameter, None)
def __setitem__(self, parameter, value):
return setattr(self, parameter, value)
my_obj = MyClass()
parameter = "x"
print(my_obj[parameter])
my_obj[parameter] = "test"
print(my_obj.x)
You need to use getarttr():
# Create a class
class myClass():
def __init__(self):
self.one = "Test"
self.two = "Plop"
# Use class
myObject = myClass()
# Define function
def myFunction(parameter):
print(getattr(myObject, parameter))##### This line is currently possible.
# Use function
myFunction("one")

Method decorator to register callbacks

I'm working on a callback system in Python. The to-be callbacks are methods of a class. I register these with a decorator.
Here is some pseudo class representing this:
class MyClass(ABC):
def __init__(self):
self.cb_stack = {}
def register_callback(self, callback, name):
self.cb_stack[name] = callback
#register_callback('mycb')
def myCallback(self, input):
self.do_things()
I suspect each decorator is executed by default.
I would like however for the decorator to be executed when obj.myCallback() is called, and to prevent myCallback() from executing at that moment (which should be the case here).
The alternative I have is to write it in the long form for each callback, which should work like so:
class MyClassLong(ABC):
def __init__(self):
self.cb_stack = {}
def register_callback(self, callback, name):
self.cb_stack[name] = callback
def myCallback(self):
def func(self, input):
self.do_things()
self.register_callback(func, 'mycb')
Notice it adds two lines of codes, so it's not really an issue but more how to make something clean.
Does anyone knows how if it is achievable, and how ?
So both of your versions have an argument input that is ignored but to a different function both times, so I don't know what you want exactly, but if we take that out, you could simpy use:
class MyClass(ABC):
def __init__(self):
self.cb_stack = {}
def register_callback(self, callback, name):
self.cb_stack[name] = callback
def myCallback(self):
self.register_callback(self.do_things, 'mycb')
class and method definitions are processed only once when the class is declared so you can only use decorators at the class level (not at the instance level). If your list of callbacks applied to all instances of the class, you could define a parameterized decorator to register them:
# defines a callback list as a dictionary
# provides the decorator
class Callbacks(dict):
def register(self,name):
def decorate(f):
self[name] = f
return f
return decorate
class MyClass:
cb_stack = Callbacks()
#cb_stack.register('mycb')
def myCallback(self, param):
print("myCallback called",param)
def triggerCallbacks(self):
for n,f in type(self).cb_stack.items(): f(self,n)
mc = MyClass()
mc.triggerCallbacks()
myCallback called mycb
You can also use this for subclasses:
class MySubclass(MyClass):
cb_stack = Callbacks(MyClass.cb_stack)
#cb_stack.register('mycb2')
def myCallback2(self, param):
print("myCallback2 called",param)
msc = MySubclass()
msc.triggerCallbacks()
myCallback called mycb
myCallback2 called mycb2

How to use a function outside a class as a property inside a class?

I'm having some problems. How we can define a function outside of a function that can be used in a class property? Also, how we can insert the self parameter into the function signature? I would like to visualize it like this:
>>> def a(self, x): #I thought maybe class will give "self" to this property function
... print(self)
...
>>> class aa:
... def __init__(self):
... pass
... #a
... def p():
... print('in it')
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in aa
TypeError: a() missing 1 required positional argument: 'x'
I want to define a function outside but to use inside of a class. Like a class's method as a property. How can I do this?
It's not really clear what you want your out-of-class function to do. There are a bunch of possibilities, but you may not know the terminology yet to describe it to us.
Here's the three I think are most likely:
You may want your function to be a decorator. That means you can apply it to a method with #decorator syntax to other functions, including methods in a class.
For this to work, your function needs to be written to accept a function object as its only argument. Whatever it returns is what will replace the function or method it was being called on, so usually you want to return a callable, but you could instead return a descriptor like property does. Try something like this:
def decorator(func):
def wrapper(self, *args, **kwargs):
print("in the wrapper")
result = func(self, *args, **kwargs)
print("wrapper is done")
return result
return wrapper
class Foo:
#decorator
def foo(self, x):
print("in foo(), x is", x)
f = Foo()
f.foo(1) # prints three messages
When you call the foo method, you're actually going to be calling the wrapper method that the decorator returned after it was applied to the original method (func). Because of how we wrote the wrapper, it will call func so the original method prints out its message too.
You may want to use property (a descriptor type) to call your out-of-class function. This is a less common way of using property than applying it as a decorator on a method, but it's not impossible. You could even have two different functions, one to be called when requesting the attribute, the other than will be called when setting it (but I'll demonstrate with just the getter):
def getter(obj):
print("in the getter")
return 1
class Foo2:
foo = property(getter)
f2 = Foo2()
print(f2.foo) # prints a message from the getter function first, then prints 1
Note that you can't use #decorator syntax when building a property this way. That is only legal syntax immediately before a function definition, and we're not defining any functions that way inside our class.
You may just want to copy a function defined outside of the class into it, without any decorator or property nonsense. This is the easiest one to do, it's just a simple assignment:
def func(self, x):
print("x is", x)
class Foo3:
method = func # just assign the global to a name in the class body
func = func # you can even use the same name if you don't mind confusing people
f3 = Foo3()
f3.method(1)
f3.func(2)
If you want to create a property that uses a function defined outside your class, it would be something like this:
def myfunc(self):
return self._p
class Foo:
def __init__(self, p):
self._p = p
p = property(myfunc)
f = Foo("Alpha")
f.p # gives "Alpha"
property accepts a function as its (first) argument. The function should have self as a parameter, and should return the value that you want the property to evaluate to.

Implementing the decorator pattern in Python

I want to implement the decorator pattern in Python, and I wondered if there is a way to write a decorator that just implements the function it wants to modify, without writing boiler-plate for all the functions that are just forwarded to the decorated object. Like so:
class foo(object):
def f1(self):
print "original f1"
def f2(self):
print "original f2"
class foo_decorator(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print "decorated f1"
self._decoratee.f1()
def f2(self): # I would like to leave that part out
self._decoratee.f2()
I would like to have calls to foo_decorator.f2 forwarded to decoratee.f2 automatically. Is there a way to write a generic method that forwards all unimplemented function-calls to decoratee?
You could use __getattr__:
class foo(object):
def f1(self):
print "original f1"
def f2(self):
print "original f2"
class foo_decorator(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print "decorated f1"
self._decoratee.f1()
def __getattr__(self, name):
return getattr(self._decoratee, name)
u = foo()
v = foo_decorator(u)
v.f1()
v.f2()
As an addendum to Philipp's answer; if you need to not only decorate, but preserve the type of an object, Python allows you to subclass an instance at runtime:
class foo(object):
def f1(self):
print "original f1"
def f2(self):
print "original f2"
class foo_decorator(object):
def __new__(cls, decoratee):
cls = type('decorated',
(foo_decorator, decoratee.__class__),
decoratee.__dict__)
return object.__new__(cls)
def f1(self):
print "decorated f1"
super(foo_decorator, self).f1()
u = foo()
v = foo_decorator(u)
v.f1()
v.f2()
print 'isinstance(v, foo) ==', isinstance(v, foo)
This is a bit more involved than strictly necessary for your example, where you know the class being decorated in advance.
This might suffice:
class foo_decorator(foo):
def __init__(self, decoratee):
self.__dict__.update(decoratee.__dict__)
def f1(self):
print "decorated f1"
super(foo_decorator, self).f1()
It's arguably not the best practice, but you can add functionality to instances, as I've done to help transition my code from Django's ORM to SQLAlachemy, as follows:
def _save(self):
session.add(self)
session.commit()
setattr(Base,'save',_save)
The UML diagram in the linked Wikipedia article is wrong and so is your code.
If you follow the "decorator pattern", the decorator class is derived from the base decorated class. (In the UML diagram an inheritance arrow from the WindowDecorator to Window is missing).
with
class foo_decorator(foo):
you don't need to implement undecorated methods.
BTW: In strong typed languages there is one more reason, why the decorator must be derived from the decorated class: Otherwise you wouldnt be able to chain decorators.
In one of my projects, I also needed to do one particular thing, that is that even the underlying object should actually execute the method that was reimplemented in the decorator. It is actually quite easy to do if you know where to target it.
The use case is:
I have an object X with methods A and B.
I create a decorator class Y that overrides A.
If I instantiate Y(X) and call A, it will use the decorated A as expected.
If B calls A, then if I instantiate Y(X) and call B on the decorator, the call from within B then goes to the old A on the original object which was undesirable. I want the old B to call the new A as well.
It is possible to reach this behaviour like this:
import inspect
import six # for handling 2-3 compatibility
class MyBaseDecorator(object):
def __init__(self, decorated):
self.decorated = decorated
def __getattr__(self, attr):
value = getattr(self.decorated, attr)
if inspect.ismethod(value):
function = six.get_method_function(value)
value = function.__get__(self, type(self))
return value
class SomeObject(object):
def a(self):
pass
def b(self):
pass
class MyDecorator(MyBaseDecorator):
def a(self):
pass
decorated = MyDecorator(SomeObject())
This may not work out of the box as I typed everything else apart from the getattr method from top of my head.
The code looks up the requested attribute in the decorated object, and if it is a method (doesn't work for properties now, but the change to support them should not be too difficult), the code then pulls the actual function out of the method and using the descriptor interface invocation it "rebinds" the function as a method, but on the decorator. Then it is returned and most likely executed.
The effect of this is that if b ever calls a on the original object, then when you have the object decorated and there is any method call coming from the decorator, the decorator makes sure that all methods accessed are bound to the decorator instead, therefore looking up things using the decorator and not the original object, therefore the methods specified in the decorator taking precedence.
P.S.: Yes I know it looks pretty much like inheritance, but this done in the sense of composition of multiple objects.
To complement #Alec Thomas reply. I modified his answer to follow the decorator pattern. This way you don't need to know the class you're decorating in advance.
class Decorator(object):
def __new__(cls, decoratee):
cls = type('decorated',
(cls, decoratee.__class__),
decoratee.__dict__)
return object.__new__(cls)
Then, you can use it as:
class SpecificDecorator(Decorator):
def f1(self):
print "decorated f1"
super(foo_decorator, self).f1()
class Decorated(object):
def f1(self):
print "original f1"
d = SpecificDecorator(Decorated())
d.f1()
In Python 3, Philipp's accepted answer raised RuntimeError: maximum recursion depth exceeded.
The way that worked for me:
class Foo(object):
def f1(self):
print("original f1")
def f2(self):
print("original f2")
class FooDecorator(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print("decorated f1")
return self._decoratee.f1()
def __getattr__(self, name):
if name in ['f1', '_decoratee']:
raise AttributeError()
return getattr(self._decoratee, name)
f = FooDecorator(Foo())
f.f1()
# decorated f1
# original f1
f.f2()
# original f2
The workaround is inspired by Ned Batchelder's blog

Overload a method with a function at runtime

OK, I'll admit upfront this is a mega kludge and that I could definately implement this better. It's only morbid curiosity that's driving me to find out how I could do this.
class SomeClass(object):
def __init__(self):
def __(self, arg):
self.doStuff(arg)
self.overLoaded = __
def doStuff(self, string):
print string
SomeClass().overLoaded("test string")
This returns a parameter error because I'm only supplying overLoaded() with one argument instead of two. Is there some magic to tell the interpreter that it's now a method of a class (I tried decorating it with #classmethod, I always understood this to be it's purpose??)
Don't worry about the self parameter, the function already has that from local scope.
class SomeClass(object):
def __init__(self):
def __(arg):
self.bar(arg)
self.foo = __
def foo(self, arg):
print "foo", arg
def bar(self, arg):
print "bar", arg
SomeClass().foo("thing") # prints "bar thing"
When creating an instance (after __new__, iirc, but before __init__) Python binds all the methods to automagically supply the instance as the first argument. If you're adding a method later then you need to supply the instance manually. As you are defining the function with self already in scope you don't need to pass it again.
Python's new module is not a solution as it has been deprecated since 2.6. If you want to create a "real" instance method do it with the partial decorator like this:
import functools
class SomeClass(object):
def __init__(self):
def __(self, arg):
self.bar(arg)
self.foo = functools.partial(__, self)
def foo(self, arg):
print "foo", arg
def bar(self, arg):
print "bar", arg
SomeClass().foo("thing") # prints "bar thing"
The issue is that you are trying to add a new instance method (not class method) and it is not binding properly. Python has a module function to manually bind functions to instances.
import new
self.method = new.instancemethod(func, self, class)
Edit: Apparently the new module is deprecated. Use the types module instead for metamagic.
import types
self.method = types.MethodType(func, self, class)
sj26's solution is a good one. Another alternative, if you want to set up a method that can be overloaded with any user-supplied function or with another of the object's methods, is build a custom descriptor. This descriptor can be used as a decorator (analogous to #classmethod or #staticmethod); and it allows you to store a function in an instance's dictionary, and returns it as a method:
import types
class overloadable(object):
def __init__(self, func):
self._default_func = func
self._name = func.__name__
def __get__(self, obj, type=None):
func = obj.__dict__.get(self._name, self._default_func)
return types.MethodType(func, obj, type)
def __set__(self, obj, value):
if hasattr(value, 'im_func'): value = value.im_func
obj.__dict__[self._name] = value
def __delete__(self, obj):
del obj.__dict__[self._name]
Now we can just decorate a function with "#overloadable":
class SomeClass(object):
def doStuff(self, string):
print 'do stuff:', string
#overloadable
def overLoaded(self, arg):
print 'default behavior:', arg
And it'll just do the right thing when we overload it for a given instance:
>>> sc = SomeClass()
>>> sc.overLoaded("test string") # Before customization
default behavior: test string
>>> sc.overLoaded = sc.doStuff # Customize
>>> sc.overLoaded("test string")
do stuff: test string
>>> del sc.overLoaded # Revert to default behavior
>>> sc.overLoaded("test string")
default behavior: test string

Categories

Resources