Unbound method in Python [duplicate] - python

This question already has answers here:
Python newbie having a problem using classes
(2 answers)
Closed 7 years ago.
In this link while explaining classes, for the following sample class
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
it is mentioned that
then MyClass.i and MyClass.f are valid attribute references, returning an integer and a function object, respectively
but when I try to print MyClass.f it gives me a error <unbound method MyClass.f>.
So what does MyClass.f returning function object really mean in this context.

It's telling you that the method isn't bound to any instance.
If you did this:
myinstance = MyClass()
myinstance.f() # "hello world"
It would work, or, you can make it static:
class MyClass
#staticmethod
def f()
print "hello world"
MyClass.f()
Would also work

Instance it:
>>> your_class = MyClass()
>>> your_class.f()
'hello world'
It's bound when you instance it:
>>> your_class.f
<bound method MyClass.f of <__main__.MyClass instance at 0x1244ef0>>

It is an instance method. You should use classmethod or staticmethod, like this:
>>> class A():
... #staticmethod
... def f(*args):
... return "hello"
...
>>> A.f
<function f at 0xb744541c>
>>> print A.f
<function f at 0xb744541c>
>>> print A.f()
hello

Related

Python: Check if a method uses #staticmethod [duplicate]

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()

Why is an object not created when a method is called during the object's contruction?

Given the class test, why it is not possible to instantiate it by calling one of its methods along with the constructor?
class test:
def __init__(self, a):
self.a = a
def print_a(self):
print(self.a)
Here is an example:
>>> obj = test("Hello").print_a() # Prints the desired output.
Hello
>>> obj
>>> print(obj) # But the object does not exist.
None
>>> obj = test("Hello") # It obviously works when doing it separately.
>>> obj
<__main__.test object at 0x7f537fea3940>
>>> obj.print_a()
Hello
Why is it not possible to chain a method call with the constructor call?
This was implemented in python3.
You are assigning obj to the return value of the function print_a (which is None as it has no return). The actual test object was never stored and is therefore no longer in scope when you try to print it.

Access Class Name From a Class Method

assuming the simple case where Foo is
class Foo:
def some_func(self):
print('hellow world')
I only have access to the variable func where func is :
func = Foo.some_func
I am trying to get the Foo class name from the variable func
func
Out[6]: <function __main__.Foo.some_func>
func.__class__.__name__
Out[7]: 'function'
I am expecting to get Foo is there anyway to do that?
Python 3 solution:
def get_class_name(func):
return func.__qualname__.split('.')[0]
__qualname__ method actually prints Foo.some_func for func.
Splitting the string by . and taking the first element, it should do the job.
Python 2 & 3 solution:
def get_class_name(func):
return func.__str__().split('.')[0].split()[-1]
Edit:
In Python 3, func.__str__() prints <function Foo.some_func at 0x10c456b70>.
In Python 2, func.__str__() prints <unbound method Foo.some_func>.

Decorator implemented as proxy class cannot decorate class-level method functions....why? [duplicate]

In Python 2.7 I'd like to decorate an instance method test in class Foo with a decorator that is also a class called FooTestDecorator. From user Chirstop's question and the Python 2 docs' Descriptor HowTo guide I created this example.
There seems to be an issue however, when I print my decorated method object, it's (inspected?) name is wrong because it is noted as a question mark like Foo.?.
import types
class FooTestDecorator(object):
def __init__(self,func):
self.func=func
self.count=0
# tried self.func_name = func.func_name, but seemed to have no effect
def __get__(self,obj,objtype=None):
return types.MethodType(self,obj,objtype)
def __call__(self,*args,**kwargs):
self.count+=1
return self.func(*args,**kwargs)
class Foo:
#FooTestDecorator
def test(self,a):
print a
def bar(self,b):
print b
if you test it:
f=Foo()
print Foo.__dict__['test']
print Foo.test
print f.test
print Foo.__dict__['bar']
print Foo.bar
print f.bar
you get
<__main__.FooTestDecorator ...object...>
<unbound method Foo.?>
<bound method Foo.? of ...instance...>
<function bar at 0x...>
<unbound method Foo.bar>
<bound method Foo.bar of ...instance...>
You can see the replacement method is shown as Foo.?. This seems wrong.
How do I get my class-decorated instance method right?
note: My reason is that I want to use variables from the FooDecorator instance's self which I would set at init. I didn't put this in the example to keep it simpler.
Your decorator instance has no __name__ attribute, so Python has to do with a question mark instead.
Use functools.update_wrapper() to copy over the function name, plus a few other interesting special attributes (such as the docstring, the function module name and any custom attributes the function may have):
import types
from functools import update_wrapper
class FooTestDecorator(object):
def __init__(self,func):
self.func=func
self.count=0
update_wrapper(self, func)
def __get__(self,obj,objtype=None):
return types.MethodType(self,obj,objtype)
def __call__(self,*args,**kwargs):
self.count+=1
return self.func(*args,**kwargs)
Demo:
>>> f=Foo()
>>> print Foo.__dict__['test']
<__main__.FooTestDecorator object at 0x11077e210>
>>> print Foo.test
<unbound method Foo.test>
>>> print f.test
<bound method Foo.test of <__main__.Foo instance at 0x11077a830>>

How to get class name when there is attribute attached? [duplicate]

This question already has answers here:
Get class that defined method
(8 answers)
Closed 8 years ago.
For example,
I want to return 'ClassName' from the following:
ClassName().MethodName
When I try:
ClassName().MethodName.__class__.__name__
>>instancemethod
or when I try:
ClassName().MethodName.__name__
>>MethodName
Perhaps this isn't possible, so would there be a way to turn ClassName().MethodName to ClassName(), so I could then run this, which is what I want:
ClassName().__class__.__name__
>> ClassName
The information you want is in the im_class attribute of the bound method object:
>>> class Foo():
... def bar():
... pass
...
>>> m = Foo().bar
>>> m.im_class
<class __main__.Foo at 0x1073bda78>
Like so:
class Foo(object):
def MethodName():
pass
print type(Foo()).__name__
# Foo
Or,
foo=Foo()
print type(foo).__name__
# Foo
(Note -- that only works on new style classes, not legacy classes. It obviously only works if you know what to call to instantiate the class)
If all you have is reference to a method, you can use inspect (Thx Alex Martelli):
import inspect
def get_class_from_method(meth):
for cls in inspect.getmro(meth.im_class):
if meth.__name__ in cls.__dict__: return cls
return None
>>> mn=Foo().MethodName
>>> get_class_from_method(mn).__name__
Foo
Or, for a user defined method, you can do:
>>> mn.im_class.__name__
Foo

Categories