I'm trying to use a python class variable as a function, using something like the following code:
class A(object):
func = None
@classmethod
def class_init(c,f):
c.func = f
def go(self, p):
A.func(p)
def my_print(p):
print(p)
A.class_init(my_print)
a = A()
a.go('AAA')
When running it using python3, everything works as expected and AAA
is printed.
Using python2, a TypeError
exception is thrown:
TypeError: unbound method my_print() must be called with A instance as first argument (got str instance instead)
It seems that python2 expects a class instance as if A.func
was an object method.
What causes this different behavior between python2 and python3?
Is there a way to "tell" python to handle A.func
as a non object method?
[I can think of walkarounds like saving A.func
as a list, meaning c.func = [f]
in class_init
and later A.func[0](p)
in go
, but would like to understand the core reason for this behavior and whether there is a neat solution]
CodePudding user response:
Since the function you want to add doesn't take a class instance or a class as its first argument, apparently you're adding a static method — so you have to explicitly tell Python that is what you are doing by manually calling the built-in staticmethod()
function.
class A(object):
func = None
@classmethod
def class_init(c, f):
c.func = staticmethod(f) # Assume function type.
def go(self, p):
A.func(p)
def my_print(p):
print(p)
A.class_init(my_print)
a = A()
a.go('AAA') #-> AAA
my_print(42) # -> 42
Alternatively you could use it outside of the class as a function decorator as shown below. One downside of doing this that it can only be called through the class or a class instance.
class A(object):
func = None
@classmethod
def class_init(c, f):
c.func = f
def go(self, p):
A.func(p)
@staticmethod
def my_print(p):
print(p)
A.class_init(my_print)
a = A()
a.go('AAA') # -> AAA
my_print(42) # -> TypeError: 'staticmethod' object is not callable