I'm trying to "wrap" an existing classmethod, i.e.,
def Foo:
#classmethod
def bar(cls, x): return x + 2
old_bar = Foo.bar
def wrapped_bar(cls, x):
result = old_bar(cls, x) # Results in an error
return result
Foo.bar = wrapped_bar
It seems that Foo.bar is already bound with cls = Foo, how do I get the unbound version of the function bar?
[I'm not allowed to modify Foo, it exists in another codebase that I'm patching]
Suppose, you have:
>>> class Foo:
... #classmethod
... def bar(cls, x):
... return x*42
...
>>> Foo.bar(2)
84
Then one way is to access the name-space of your class directly. Then you should be able to access the classmethod object and obtain the decorated function available at the __func__ attribute:
>>> vars(Foo)['bar']
<classmethod object at 0x103eec520>
>>> vars(Foo)['bar'].__func__
<function Foo.bar at 0x1043e49d0>
Alternatively, it is accessible on the bound-method object itself:
>>> bound = Foo.bar
>>> bound
<bound method Foo.bar of <class '__main__.Foo'>>
>>> bound.__func__
<function Foo.bar at 0x1043e49d0>
The __func__ attribute holds the wrapped method. Note that your wrapper will also need the #classmethod decorator in order to attach properly (otherwise it'll act as an instance method).
#classmethod
def wrapped_bar(cls, x):
result = Foo.bar.__func__(cls, x)
return result
Foo.bar = wrapped_bar
Related
Here __class__ should not be confused with self.__class__ which I am already able to access with the inspect module:
import inspect
class A:
def __init__(self):
print(__class__.__name__) # I want to move this statement inside f
f()
class B(A):
pass
def f():
prev_frame = inspect.currentframe().f_back
self = prev_frame.f_locals["self"]
print(self.__class__.__name__)
B() # prints A B
The implicit __class__ reference is created at compile-time only if you actually reference it within the method (or use super). For example this code:
class Foo:
def bar(self):
print('bar', locals())
def baz(self):
print('baz', locals())
if False:
__class__
if __name__ == '__main__':
foo = Foo()
foo.bar()
foo.baz()
Produces this output:
bar {'self': <__main__.Foo object at 0x10f45f978>}
baz {'self': <__main__.Foo object at 0x10f45f978>, '__class__': <class '__main__.Foo'>}
To find the calling function's class (in most cases) you could chain together a few CPython-specific inspect incantations:
Find the calling function: How to get current function into a variable?
Find that function's class: Get defining class of unbound method object in Python 3
I wouldn't recommend it.
##### Case 1, use property #####
class Case1:
# ignore getter and setter for property
var = property(getter, setter, None, None)
##### Case 2, use equivalent methods ####
class Descriptor:
def __get__(self, obj, type=None):
return None
def __set__(self, obj, val):
pass
class Case2:
var = Descriptor()
My question is:
When I use 'property' to control the access of one variable,
instance.var will correctly return the real value,
while Class.var will return the property object itself (e.g. property object at 0x7fc5215ac788)
But when I use equivalent methods (e.g. descriptor) and override __get__ and __set__ methods,
both instance.var and Class.var can return the real value instead of the object itself.
So why they behave so differently?
I guess it is because some of default functions implemented in the my descriptor make the magic, so what are they?
update:
The reason for the above question is that __get__ function implemented in the property will determine if it is called by instance or Class, and when it is called by Class, it will return the object itself (i.e. self).
But as __set__ function does not have type or cls parameter, and based on my test, Class.var = 5 cannot be caught by __set__ function.
Therefore, I wonder what hooks we can use to customize the class variable level assignment Class.var = value?
When you do MyClass.some_descriptor, there's (obviously) no instance to be passed to the descriptor, so it is invoked with obj=None:
>>> class Desc(object):
... def __get__(self, obj, cls=None):
... print "obj : {} - cls : {}".format(obj, cls)
... return 42
...
>>> class Foo(object):
... bar = Desc()
...
>>> Foo.bar
obj : None - cls : <class '__main__.Foo'>
42
>>> Foo().bar
obj : <__main__.Foo object at 0x7fd285cf4a90> - cls : <class '__main__.Foo'>
42
>>>
In most cases (and specially with the generic property descriptor) the goal is to compute the return value based on instance attributes so there's not much you can return without the instance. In this case, most authors choose to return the descriptor instance itself so it can be correctly identified for what it is when inspecting the class.
If you want this behaviour (which makes sense for most descriptors), you just have to test obj against None and return self:
>>> class Desc2(object):
... def __get__(self, obj, cls=None):
... if obj is None:
... return self
... return 42
...
>>> Foo.baaz = Desc2()
>>> Foo.baaz
<__main__.Desc2 object at 0x7fd285cf4b10>
>>> Foo().baaz
42
>>>
And that's all the "magic" involved .
Now if you wonder why this is not the default: there are use cases for returning something else for a descriptor looked up on a class - methods for example (yes, Python functions are descriptors - their __get__ method returns a method object, which is actually a callable wrapper around the instance (if any), class and function):
>>> Foo.meth = lambda self: 42
>>> Foo.meth
<unbound method Foo.<lambda>>
>>> Foo().meth
<bound method Foo.<lambda> of <__main__.Foo object at 0x7fd285cf4bd0>>
>>> Foo.meth(Foo())
42
This question already has an answer here:
python - call instance method using __func__
(1 answer)
Closed 5 years ago.
I have a code where I want to 'steal' methods of other class in run-time. (It's a small game and I want to allow bots to change strategy on-demand).
Example:
class X(object):
def foo(self):
return 1
class Y(object):
def foo(self):
return 2
I want to 'copy' Y.foo into instance of X class:
x.foo = Y.foo
x.foo() # unbound method
x.foo = types.MethodType(Y.foo, x)
x.foo() # TypeError: unbound method foo() must be called with Y instance as first argument (got X instance instead
tmp=x.foo.__self__
x.foo=Y.foo
x.foo.__self__ = tmp # readonly attribute
x.foo.__func__ = Y.bar.__func__ # readonly attribute
Is there any way to copy function from one class into other in runtime, without:
Inheritance (it should be done inside method of instanced class)
calling Y.bar from within x.foo
In Python 2, accessing a method on the class returns an unbound method. Simply unwrap that method to get the original function, using the __func__ attribute:
x.foo = types.MethodType(Y.foo.__func__, x)
You could tell that function to bind using the descriptor protocol:
x.foo = Y.foo.__func__.__get__(x)
Demo:
>>> class X(object):
... def foo(self):
... return 1
...
>>> class Y(object):
... def foo(self):
... return 2
...
>>> x = X()
>>> Y.foo
<unbound method Y.foo>
>>> Y.foo.__func__
<function foo at 0x1006d1b18>
>>> Y.foo.__func__.__get__(x)
<bound method ?.foo of <__main__.X object at 0x1006e84d0>>
>>> x.foo = Y.foo.__func__.__get__(x)
>>> x.foo()
2
TL;DR How do I find out whether a function was defined using #classmethod or something with the same effect?
My problem
For implementing a class decorator I would like to check if a method takes the class as its first argument, for example as achieved via
#classmethod
def function(cls, ...):
I found a solution to check for #staticmethod via the types module (isinstance(foo, types.UnboundMethodType) is False if the foo is static, see here), but did not find anything on how to do so for #classmethod
Context
What I am trying to do is something along the lines of
def class_decorator(cls):
for member in cls.__dict__:
if (isclassmethod(getattr(cls, member))):
# do something with the method
setattr(cls, member, modified_method)
return cls
and I do not know how to implement what I called isclassmethod in this example
If the object is a method object, and so has a method.__self__ attribute, and that attribute is the class you got the attribute from, then it'll take the class as the first argument. It has been bound to the class.
Note that you already have a bound object at this point, so you don't need to pass in the class again, unless you first extract the original function from method.__func__.
Here is an illustration, the class Foo has a class method bar and a regular method baz, which is not bound when you access it directly on the class:
>>> class Foo:
... #classmethod
... def bar(cls):
... pass
... def baz(self):
... pass
...
>>> Foo.baz
<function Foo.baz at 0x1097d1e18>
>>> Foo.bar
<bound method Foo.bar of <class '__main__.Foo'>>
>>> Foo.bar.__self__
<class '__main__.Foo'>
>>> Foo.bar.__self__ is Foo
True
Calling Foo.bar() automatically passes in Foo.bar.__self__ as the first argument.
If you need to test such methods, use inspect.ismethod(), and if that returns True test the __self__ attribute:
import inspect
if inspect.ismethod(cls.method) and cls.method.__self__ is cls:
# method bound to the class, e.g. a classmethod
This should work for any custom descriptors that work like classmethod does, as well.
If you need to know with certainty that the method was produced by a classmethod object, you'll need to look up the attributes directly in the class namespace (cls.__dict__ or vars(cls)), and do so in each class in the class hierarchy in method resolution order:
def isclassmethod(method):
bound_to = getattr(method, '__self__', None)
if not isinstance(bound_to, type):
# must be bound to a class
return False
name = method.__name__
for cls in bound_to.__mro__:
descriptor = vars(cls).get(name)
if descriptor is not None:
return isinstance(descriptor, classmethod)
return False
and a full test of the above two approaches using a base class and a derived class, with a custom descriptor that binds a function the same way a classmethod would, but is not, itself, a classmethod:
>>> class notclassmethod:
... def __init__(self, f):
... self.f = f
... def __get__(self, _, typ=None):
... return self.f.__get__(typ, typ)
...
>>> class Base:
... #classmethod
... def base_cm(cls): pass
... #notclassmethod
... def base_ncm(cls): pass
... def base_m(self): pass
...
>>> class Derived(Base):
... #classmethod
... def derived_cm(cls): pass
... #notclassmethod
... def derived_ncm(cls): pass
... def derived_m(self): pass
...
>>> inspect.ismethod(Derived.base_cm) and Derived.base_cm.__self__ is Derived
True
>>> inspect.ismethod(Derived.base_ncm) and Derived.base_ncm.__self__ is Derived
True
>>> inspect.ismethod(Derived.base_m) and Derived.base_m.__self__ is Derived
False
>>> inspect.ismethod(Derived.derived_cm) and Derived.derived_cm.__self__ is Derived
True
>>> inspect.ismethod(Derived.derived_ncm) and Derived.derived_ncm.__self__ is Derived
True
>>> inspect.ismethod(Derived.derived_m) and Derived.derived_m.__self__ is Derived
False
>>> isclassmethod(Derived.base_cm)
True
>>> isclassmethod(Derived.base_ncm)
False
>>> isclassmethod(Derived.base_m)
False
>>> isclassmethod(Derived.derived_cm)
True
>>> isclassmethod(Derived.derived_ncm)
False
>>> isclassmethod(Derived.derived_m)
False
The isclassmethod() function correctly distinguishes between the classmethod and notclassmethod descriptors.
Historical note: this answer included references to Python 2, but with Python 2 having reached EOL were removed as no longer relevant.
You should use inspect.ismethod. It works because classmethod binds the function to the class object. See the following code:
>>> class Foo:
... #classmethod
... def bar():
... pass
... def baz():
... pass
...
>>> Foo.bar
<bound method type.bar of <class '__main__.Foo'>>
>>> Foo.baz
<function Foo.baz at 0x0000000002CCC1E0>
>>> type(Foo.bar)
<class 'method'>
>>> type(Foo.baz)
<class 'function'>
>>> import inspect
>>> inspect.ismethod(Foo.bar)
True
>>> inspect.ismethod(Foo.baz)
False
class Foo(object):
#classmethod
def baaz(cls):
print "baaz"
isinstance(Foo.__dict__["baaz"], classmethod)
None of the answers address the problem of identifying whether a method is decorated with class method from an instance of the class. Following code explores the class dict of an instance to distinguish between classmethod from other methods.
class MyClass(object):
#classmethod
def class_method(cls):
pass
def instance_method(self):
pass
#staticmethod
def static_method():
pass
def blas(): pass
t = MyClass()
isinstance(t.__class__.__dict__[t.class_method.__name__], classmethod) # True
isinstance(t.__class__.__dict__[t.static_method.__name__], classmethod) # False
isinstance(t.__class__.__dict__[t.instance_method.__name__], classmethod) # False
isinstance(t.__class__.__dict__[t.blas.__name__], classmethod) # False
This will work for both Python 2 and 3.
This works for me:
def is_classmethod(method):
"""
Is method a classmethod?
"""
return isinstance(getattr(method, '__self__', None), type)
It basically tests if method.__self__ exists and is a class, as in Martijn's answer, but does not require access to the class itself.
assume following class definition:
class A:
def f(self):
return 'this is f'
#staticmethod
def g():
return 'this is g'
a = A()
So f is a normal method and g is a static method.
Now, how can I check if the funcion objects a.f and a.g are static or not? Is there a "isstatic" funcion in Python?
I have to know this because I have lists containing many different function (method) objects, and to call them I have to know if they are expecting "self" as a parameter or not.
Lets experiment a bit:
>>> import types
>>> class A:
... def f(self):
... return 'this is f'
... #staticmethod
... def g():
... return 'this is g'
...
>>> a = A()
>>> a.f
<bound method A.f of <__main__.A instance at 0x800f21320>>
>>> a.g
<function g at 0x800eb28c0>
>>> isinstance(a.g, types.FunctionType)
True
>>> isinstance(a.f, types.FunctionType)
False
So it looks like you can use types.FunctionType to distinguish static methods.
Your approach seems a bit flawed to me, but you can check class attributes:
(in Python 2.7):
>>> type(A.f)
<type 'instancemethod'>
>>> type(A.g)
<type 'function'>
or instance attributes in Python 3.x
>>> a = A()
>>> type(a.f)
<type 'method'>
>>> type(a.g)
<type 'function'>
To supplement the answers here, in Python 3 the best way is like so:
import inspect
class Test:
#staticmethod
def test(): pass
isstatic = isinstance(inspect.getattr_static(Test, "test"), staticmethod)
We use getattr_static rather than getattr, since getattr will retrieve the bound method or function, not the staticmethod class object. You can do a similar check for classmethod types and property's (e.g. attributes defined using the #property decorator)
Note that even though it is a staticmethod, don't assume it was defined inside the class. The method source may have originated from another class. To get the true source, you can look at the underlying function's qualified name and module. For example:
class A:
#staticmethod:
def test(): pass
class B: pass
B.test = inspect.getattr_static(A, "test")
print("true source: ", B.test.__qualname__)
Technically, any method can be used as "static" methods, so long as they are called on the class itself, so just keep that in mind. For example, this will work perfectly fine:
class Test:
def test():
print("works!")
Test.test()
That example will not work with instances of Test, since the method will be bound to the instance and called as Test.test(self) instead.
Instance and class methods can be used as static methods as well in some cases, so long as the first arg is handled properly.
class Test:
def test(self):
print("works!")
Test.test(None)
Perhaps another rare case is a staticmethod that is also bound to a class or instance. For example:
class Test:
#classmethod
def test(cls): pass
Test.static_test = staticmethod(Test.test)
Though technically it is a staticmethod, it is really behaving like a classmethod. So in your introspection, you may consider checking the __self__ (recursively on __func__) to see if the method is bound to a class or instance.
I happens to have a module to solve this. And it's Python2/3 compatible solution. And it allows to test with method inherit from parent class.
Plus, this module can also test:
regular attribute
property style method
regular method
staticmethod
classmethod
For example:
class Base(object):
attribute = "attribute"
#property
def property_method(self):
return "property_method"
def regular_method(self):
return "regular_method"
#staticmethod
def static_method():
return "static_method"
#classmethod
def class_method(cls):
return "class_method"
class MyClass(Base):
pass
Here's the solution for staticmethod only. But I recommend to use the module posted here.
import inspect
def is_static_method(klass, attr, value=None):
"""Test if a value of a class is static method.
example::
class MyClass(object):
#staticmethod
def method():
...
:param klass: the class
:param attr: attribute name
:param value: attribute value
"""
if value is None:
value = getattr(klass, attr)
assert getattr(klass, attr) == value
for cls in inspect.getmro(klass):
if inspect.isroutine(value):
if attr in cls.__dict__:
bound_value = cls.__dict__[attr]
if isinstance(bound_value, staticmethod):
return True
return False
Why bother? You can just call g like you call f:
a = A()
a.f()
a.g()