Home > front end >  Using python 2.7 class variable as a function
Using python 2.7 class variable as a function

Time:03-15

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
  • Related