how to construct methods dynamically? - python

I have designed a class. It is pretty standard, with some method attributes
class foo:
def f1(self):
print 'f1'
def f2(self):
print 'f2'
....
def fn(self):
print 'fn'
Now I would like to create a class which contains a set of foo instances.
class bar:
self.myfoos=[foo(),foo(),foo()]
I would then like to class the f1..fn methods on all the foo instances.
I could do:
class bar:
...
def f1():
for foo_ in self.myfoos:
foo_.f1()
However, my list of f1..fn is quite long so how could I obtain this behavior in a succint way?Maybe with alternative design completely?

You could just implement __getattr__ and delegate that call to list of foos. I'm sure there is a more elegant way to do this:
class foo:
def f1(self):
print('f1')
def f2(self):
print('f2')
class bar:
def __init__(self):
self.foos = [foo() for _ in range(3)]
def __getattr__(self, fn):
def fns(*args, **kwargs):
for f in self.foos:
getattr(f, fn)(*args, **kwargs)
return fns
In []:
b = bar()
b.f1()
Out[]
f1
f1
f1
In []:
b.f2()
Out[]:
f2
f2
f2

You're looking for a way to construct a bunch of methods dynamically. This is often not a good idea—but sometimes it is. (For example, consider libraries like PyObjC and pythoncom that build dynamic proxies to ObjC and COM classes that you don't even know about until runtime. How else could you do that?)
So, you should definitely think through whether you actually want and need this—but, if you do, there are two basic approaches.
Building a static class dynamically
If you're only trying to wrap up a collection of foo objects, you can create all the methods in a loop. Methods aren't anything too magical; you just define them the same as any other function, and assign them to the class.
The only tricky bit there is that you can't just write bar.f1 = …, because f1 is only available as a string. So we have to use setattr to do it:
class bar:
# your existing stuff
for name in 'f1 f2 f3 f4 f5 f6 f7 f8'.split():
foometh = getattr(foo, name)
def f(self):
for foo in self.myfoos:
foometh(foo)
f.__name__ = name
setattr(bar, name, f)
If there's some kind of rule that specifies which methods you want to forward, instead of a list of a bunch of method names, you'd do something like:
for name, foometh in inspect.getmembers(foo):
if name.startswith('_') or not isinstance(foometh, types.FunctionType)) or <rest of your rule>:
continue
def f(self):
# from here it's the same as above
Building a dynamic class statically
If you're trying to wrap up anything that meets some basic qualifications, rather than some specific list of methods of some specific class, you won't know what you want to wrap up, or how you want to wrap it, until someone tries to call those methods. So you have to catch the attempt to look up an unknown method, and build the wrapper on the fly. For this, we override __getattr__:
class bar:
# your existing stuff
def __getattr__(self, attr):
if attr.startswith('_') or <other rules here>:
raise AttributeError
def f():
for foo in self.myfoos:
foometh(foo)
f.__name__ = attr
return f
This version returns functions that act like bound methods if you don't look too closely, rather than actual bound methods that can be introspected. If you want the latter, bind a method explicitly, by adding self as a parameter to f, and then calling __get__ on f and returning the result. (And if you don't know what that means, you don't want to write this part…)

Related

How can I refer to the currently being defined class? [duplicate]

For a recursive function we can do:
def f(i):
if i<0: return
print i
f(i-1)
f(10)
However is there a way to do the following thing?
class A:
# do something
some_func(A)
# ...
If I understand your question correctly, you should be able to reference class A within class A by putting the type annotation in quotes. This is called forward reference.
class A:
# do something
def some_func(self, a: 'A')
# ...
See ref below
https://github.com/python/mypy/issues/3661
https://www.youtube.com/watch?v=AJsrxBkV3kc
In Python you cannot reference the class in the class body, although in languages like Ruby you can do it.
In Python instead you can use a class decorator but that will be called once the class has initialized. Another way could be to use metaclass but it depends on what you are trying to achieve.
You can't with the specific syntax you're describing due to the time at which they are evaluated. The reason the example function given works is that the call to f(i-1) within the function body is because the name resolution of f is not performed until the function is actually called. At this point f exists within the scope of execution since the function has already been evaluated. In the case of the class example, the reference to the class name is looked up during while the class definition is still being evaluated. As such, it does not yet exist in the local scope.
Alternatively, the desired behavior can be accomplished using a metaclass like such:
class MetaA(type):
def __init__(cls):
some_func(cls)
class A(object):
__metaclass__=MetaA
# do something
# ...
Using this approach you can perform arbitrary operations on the class object at the time that the class is evaluated.
Maybe you could try calling __class__.
Right now I'm writing a code that calls a class method from within the same class.
It is working well so far.
I'm creating the class methods using something like:
#classmethod
def my_class_method(cls):
return None
And calling then by using:
x = __class__.my_class_method()
It seems most of the answers here are outdated. From python3.7:
from __future__ import annotations
Example:
$ cat rec.py
from __future__ import annotations
class MyList:
def __init__(self,e):
self.data = [e]
def add(self, e):
self.data.append(e)
return self
def score(self, other:MyList):
return len([e
for e in self.data
if e in other.data])
print(MyList(8).add(3).add(4).score(MyList(4).add(9).add(3)))
$ python3.7 rec.py
2
Nope. It works in a function because the function contents are executed at call-time. But the class contents are executed at define-time, at which point the class doesn't exist yet.
It's not normally a problem because you can hack further members into the class after defining it, so you can split up a class definition into multiple parts:
class A(object):
spam= 1
some_func(A)
A.eggs= 2
def _A_scramble(self):
self.spam=self.eggs= 0
A.scramble= _A_scramble
It is, however, pretty unusual to want to call a function on the class in the middle of its own definition. It's not clear what you're trying to do, but chances are you'd be better off with decorators (or the relatively new class decorators).
There isn't a way to do that within the class scope, not unless A was defined to be something else first (and then some_func(A) will do something entirely different from what you expect)
Unless you're doing some sort of stack inspection to add bits to the class, it seems odd why you'd want to do that. Why not just:
class A:
# do something
pass
some_func(A)
That is, run some_func on A after it's been made. Alternately, you could use a class decorator (syntax for it was added in 2.6) or metaclass if you wanted to modify class A somehow. Could you clarify your use case?
If you want to do just a little hacky thing do
class A(object):
...
some_func(A)
If you want to do something more sophisticated you can use a metaclass. A metaclass is responsible for manipulating the class object before it gets fully created. A template would be:
class AType(type):
def __new__(meta, name, bases, dct):
cls = super(AType, meta).__new__(meta, name, bases, dct)
some_func(cls)
return cls
class A(object):
__metaclass__ = AType
...
type is the default metaclass. Instances of metaclasses are classes so __new__ returns a modified instance of (in this case) A.
For more on metaclasses, see http://docs.python.org/reference/datamodel.html#customizing-class-creation.
If the goal is to call a function some_func with the class as an argument, one answer is to declare some_func as a class decorator. Note that the class decorator is called after the class is initialized. It will be passed the class that is being decorated as an argument.
def some_func(cls):
# Do something
print(f"The answer is {cls.x}")
return cls # Don't forget to return the class
#some_func
class A:
x = 1
If you want to pass additional arguments to some_func you have to return a function from the decorator:
def some_other_func(prefix, suffix):
def inner(cls):
print(f"{prefix} {cls.__name__} {suffix}")
return cls
return inner
#some_other_func("Hello", " and goodbye!")
class B:
x = 2
Class decorators can be composed, which results in them being called in the reverse order they are declared:
#some_func
#some_other_func("Hello", "and goodbye!")
class C:
x = 42
The result of which is:
# Hello C and goodbye!
# The answer is 42
What do you want to achieve? It's possible to access a class to tweak its definition using a metaclass, but it's not recommended.
Your code sample can be written simply as:
class A(object):
pass
some_func(A)
If you want to refer to the same object, just use 'self':
class A:
def some_func(self):
another_func(self)
If you want to create a new object of the same class, just do it:
class A:
def some_func(self):
foo = A()
If you want to have access to the metaclass class object (most likely not what you want), again, just do it:
class A:
def some_func(self):
another_func(A) # note that it reads A, not A()
Do remember that in Python, type hinting is just for auto-code completion therefore it helps IDE to infer types and warn user before runtime. In runtime, type hints almost never used(except in some cases) so you can do something like this:
from typing import Any, Optional, NewType
LinkListType = NewType("LinkList", object)
class LinkList:
value: Any
_next: LinkListType
def set_next(self, ll: LinkListType):
self._next = ll
if __name__ == '__main__':
r = LinkList()
r.value = 1
r.set_next(ll=LinkList())
print(r.value)
And as you can see IDE successfully infers it's type as LinkList:
Note: Since the next can be None, hinting this in the type would be better, I just didn't want to confuse OP.
class LinkList:
value: Any
next: Optional[LinkListType]
It's ok to reference the name of the class inside its body (like inside method definitions) if it's actually in scope... Which it will be if it's defined at top level. (In other cases probably not, due to Python scoping quirks!).
For on illustration of the scoping gotcha, try to instantiate Foo:
class Foo(object):
class Bar(object):
def __init__(self):
self.baz = Bar.baz
baz = 15
def __init__(self):
self.bar = Foo.Bar()
(It's going to complain about the global name 'Bar' not being defined.)
Also, something tells me you may want to look into class methods: docs on the classmethod function (to be used as a decorator), a relevant SO question. Edit: Ok, so this suggestion may not be appropriate at all... It's just that the first thing I thought about when reading your question was stuff like alternative constructors etc. If something simpler suits your needs, steer clear of #classmethod weirdness. :-)
Most code in the class will be inside method definitions, in which case you can simply use the name A.

How to pass an instance method, that uses instance variables, as argument to another function?

I want to pass a method foo of an instance of a class A to another function run_function. The method foo will use instance variables of its class A.
Here is a minimal example, in which the instance variable of A is simply self.a_var, and foo just prints that variable.
class A:
def __init__(self,a_var):
self.a_var=a_var
def foo(self):
print(self.a_var)
class B:
def __init__(self, A):
self.A=A
# EDIT (comment to compile)
self.A.do_something()
def run_function(self):
self.A.foo()
def run_function_2(self, bar):
bar()
myA = A(42)
myA.foo()
# Current implementation
myB=B(myA)
myB.run_function()
# Better(?) implementation
myB.run_function_2(myA.foo)
At the moment I pass the instance myA of class A to the instance of B and explicitly call self.A.foo(). This forces the name of the function of Ato be foo. Which is stupid.
The better (?) implementation passes the function of the instance to run_function2. This works, but I am not sure if this is "safe".
Question:
Are there any loopholes that I don't see at the moment?
The important part is, that the method foo, that is passed, needs to access instance variables of the (its) class instance. So, will foo that is called inside run_function_2 always have access to all instance variables of myA?
Is there a better way to implement this?
EDIT: I forgot to add, that class B will always have an instance of A, since it has to do_something with that instance. Maybe that will change something(?). Sorry!
For your second implementation, have you considered the following:
>>> myAa = A(42)
>>> myAb = A(43)
>>> myB = B(myAb)
>>> myB.run_function_2(myAa.foo)
42
This might not be what you want. How about using getattr() and just passing in the desired method name:
>>> class C:
... def __init__(self, A):
... self.A = A
... def run_fct(self, bar):
... fct = getattr(self.A, bar)
... fct()
...
>>> myC = C(myAa)
>>> myC.run_fct('foo')
42
To answer your questions:
Any function executed in the context of an object instance will have access to the instance variables.
There may be a better way to implement this, you could try defining an interface for class A and other classes that might be like it. The you know that the function will always be called foo(). If not, I'd question why it is you need to have some object call an arbitrary method on another object. If you can give more concrete examples about what you're trying to do it would help.
The main difference between run_function and run_function_2 is that the former calls foo on the object that was given to the B() constructor. run_function_2 is independent of what object is saved as self.A; it just calls the function/method you give it. For example
class A:
def __init__(self,a_var):
self.a_var=a_var
def foo(self):
print(self.a_var)
class B:
def __init__(self, A):
self.A=A
def run_function(self):
self.A.foo()
def run_function_2(self, bar):
bar()
myA = A(42)
myB = B(myA)
myA2 = A(3.14)
myB.run_function()
myB.run_function_2(myA.foo)
myB.run_function_2(myA2.foo)
Output
42
42
3.14
Are there any loopholes that I don't see at the moment?
These two ways of calling methods are fine. Though I agree that function_run_2 is more convenient since it doesn't fix the method name, it makes you ask... what's the purpose of giving an A object to the B constructor in the first place if it's never used?
The important part is, that the method foo, that is passed, needs to access instance variables of the (its) class instance. So, will foo that is called inside run_function_2 always have access to all instance variables of myA?
Yes. run_function_2 arguments requires a function. In this case, you pass myA.foo, an object myA's method defined in class A. When you call foo inside run_function_2, you are only dealing with attributes variables of the instance myA; this is the idea of encapsulation in classes.
Is there a better way to implement this?
Answering also your question on safety, it's perfectly safe. Functions and methods are objects in Python, and they can be passed around like values. You're basically leaning on the idea of function currying or partial functions. See How do I pass a method as a parameter in Python. These two ways are fine.

Rename Methods on the Fly

We can rename class methods at class definition time with a metaclass. This question is not about that.
This is more of a thought experiment, so humour me a little please.
Say I wanted to write two decorators that are used like this:
class SomeClass(object):
#append_A
def some_method( self ):
pass
#append_B
def some_method( self ):
pass
Which would result in SomeClass having two methods: some_method_A and some_method_B
Is this possible and if so, can you point me in the right direction?
I've tried changing the frame's f_locals a few different ways, but the method name still persists.
No, it's not possible to change method names using decorator, as explained in the documentation:
The decorator syntax is merely syntactic sugar, the following two function definitions are semantically equivalent:
def f(...):
...
f = staticmethod(f)
#staticmethod
def f(...):
...
More syntax discussion goes here.
Update
I guess we could do something like leave the method alone in the decorator but also add a new method with an edited name in the scope it was defined (this case the class). The main thing is defining two methods with the same name then ending up with two differently named methods which are passed to the metaclass.
For this purpose you can use the class decorator:
def append_B(func):
func.suffix='_B'
return func
def appendable(class_obj):
for name in dir(class_obj):
if not name.startswith('_'):
attr = class_obj.__dict__[name] #getattr(class_obj, name)
suffix = getattr(attr, 'suffix', None)
if isinstance(suffix,str):
attr.suffix = None
setattr(class_obj,name+suffix, getattr(class_obj, name))
#delattr(class_obj,name)
return class_obj
The following usage allows you to define two names for the same method:
#appendable
class B(object):
#append_B
def some_method(s):
print 'B.some_method'
b=B()
b.some_method()
b.some_method_B()

(Un)Pickle Class having Instancemethod Objects

I have a class (Bar) which effectively has its own state and callback(s) and is used by another class (Foo):
class Foo(object):
def __init__(self):
self._bar = Bar(self.say, 10)
self._bar.work()
def say(self, msg):
print msg
class Bar(object):
def __init__(self, callback, value):
self._callback = callback
self._value = value
self._more = { 'foo' : 1, 'bar': 3, 'baz': 'fubar'}
def work(self):
# Do some work
self._more['foo'] = 5
self._value = 10
self._callback('FooBarBaz')
Foo()
Obviously I can't pickle the class Foo since Bar has an instancemethod, so I'm left with the following solution of implementing __getstate__ & __setstate__ in Bar to save self._value & self._more, but I have to instantiate the self._callback method as well (i.e. call __init__() from the outer class Foo passing the callback function.
But I cannot figure out how to achieve this.
Any help is much appreciated.
Thanks.
I think if you need to serialize something like this you need to be able to define your callback as a string. For example, you might say that callback = 'myproject.callbacks.foo_callback'.
Basically in __getstate__ you'd replace the _callback function with something you could use to look up the function later like self._callback.__name__.
In __setstate__ you'd replace _callback with a function.
This depends on your functions all having real names so you couldn't use a lambda as a callback and expect it to be serialized. You'd also need a reasonable mechanism for looking up your functions by name.
You could potentially use __import__ (something like: 'myproject.somemodule.somefunc' dotted name syntax could be supported that way, see http://code.google.com/p/mock/source/browse/mock.py#1076) or just define a lookup table in your code.
Just a quick (untested, sorry!) example assuming you have a small set of possible callbacks defined in a lookup table:
def a():
pass
callbacks_to_name = {a: 'a'
# ...
}
callbacks_by_name = {'a': a,
# ...
}
class C:
def __init__(self, cb):
self._callback = cb
def __getstate__(self):
self._callback = callbacks_to_name[self._callback]
return self.__dict__
def __setstate__(self, state):
state[_callback] = callbacks_by_name[self._callback]
I'm not sure what your use case is but I'd recommend doing this by serializing your work items to JSON or XML and writing a simple set of functions to serialize and deserialize them yourself.
The benefit is that the serialized format can be read and understood by humans and modified when you upgrade your software. Pickle is tempting because it seems close enough, but by the time you have a serious pile of __getstate__ and __setstate__ you haven't really saved yourself much effort or headache over building your own scheme specifically for your application.

Python: Hack to call a method on an object that isn't of its class

Assume you define a class, which has a method which does some complicated processing:
class A(object):
def my_method(self):
# Some complicated processing is done here
return self
And now you want to use that method on some object from another class entirely. Like, you want to do A.my_method(7).
This is what you'd get: TypeError: unbound method my_method() must be called with A instance as first argument (got int instance instead).
Now, is there any possibility to hack things so you could call that method on 7? I'd want to avoid moving the function or rewriting it. (Note that the method's logic does depend on self.)
One note: I know that some people will want to say, "You're doing it wrong! You're abusing Python! You shouldn't do it!" So yes, I know, this is a terrible terrible thing I want to do. I'm asking if someone knows how to do it, not how to preach to me that I shouldn't do it.
Of course I wouldn't recommend doing this in real code, but yes, sure, you can reach inside of classes and use its methods as functions:
class A(object):
def my_method(self):
# Some complicated processing is done here
return 'Hi'
print(A.__dict__['my_method'](7))
# Hi
You can't. The restriction has actually been lifted in Python 3000, but I presume you are not using that.
However, why can't you do something like:
def method_implementation(self, x,y):
# do whatever
class A():
def method(self, x, y):
return method_implementation(self, x, y)
If you are really in the mood for python abuse, write a descriptor class that implements the behavior. Something like
class Hack:
def __init__(self, fn):
self.fn = fn
def __get__(self, obj, cls):
if obj is None: # called staticly
return self.fn
else:
def inner(*args, **kwargs):
return self.fn(obj, *args, **kwargs)
return inner
Note that this is completely untested, will probably break some corner cases, and is all around evil.
def some_method(self):
# Some complicated processing is done here
return self
class A(object):
my_method = some_method
a = A()
print some_method
print a.my_method
print A.my_method
print A.my_method.im_func
print A.__dict__['my_method']
prints:
<function some_method at 0x719f0>
<bound method A.some_method of <__main__.A object at 0x757b0>>
<unbound method A.some_method>
<function some_method at 0x719f0>
<function some_method at 0x719f0>
It sounds like you're looking up a method on a class and getting an unbound method. An unbound method expects a object of the appropriate type as the first argument.
If you want to apply the function as a function, you've got to get a handle to the function version of it instead.
You could just put that method into a superclass of the two objects that need to call it, couldn't you? If its so critical that you can't copy it, nor can you change it to not use self, thats the only other option I can see.
>>> class A():
... me = 'i am A'
...
>>> class B():
... me = 'i am B'
...
>>> def get_name(self):
... print self.me
...
>>> A.name = get_name
>>> a=A()
>>> a.name()
i am A
>>>
>>> B.name = get_name
>>> b=B()
>>> b.name()
i am B
>>>
Why cant you do this
class A(object):
def my_method(self,arg=None):
if (arg!=None):
#Do Some Complicated Processing with both objects and return something
else:
# Some complicated processing is done here
return self
In Python functions are not required to be enclosed in classes. It sounds like what you need is utility function, so just define it as such:
def my_function(object):
# Some complicated processing is done here
return object
my_function(7)
my_function("Seven")
As long as your processing is using methods and attribute available on all objects that you pass to my_function through the magic of duck typing everything will work fine.
That's what's called a staticmethod:
class A(object):
#staticmethod
def my_method(a, b, c):
return a, b, c
However in staticmethods, you do not get a reference to self.
If you'd like a reference to the class not the instance (instance implies reference to self), you can use a classmethod:
class A(object):
classvar = "var"
#classmethod
def my_method(cls, a, b, c):
print cls.classvar
return a, b, c
But you'll only get access to class variables, not to instance variables (those typically created/defined inside the __init__ constructor).
If that's not good enough, then you will need to somehow pass a "bound" method or pass "self" into the method like so:
class A(object):
def my_method(self):
# use self and manipulate the object
inst = A()
A.my_method(inst)
As some people have already said, it's not a bad idea to just inherit one class from the other:
class A(object):
... methods ...
class B(A):
def my_method(self):
... use self
newA = B()

Categories