简体   繁体   中英

Can we call a user-defined instance method inside a @classmethod function?

I try to call a method inside a method with decorator @classmethod, any idea how to achieve this? For example I have:

class A():
    def B(self):
    #do something
    return something

    @classmethod
    def C(cls):
    #do something
    x = B() #call B method
    return None

I've got an error:

NameError: global name 'B' is not defined

Can I call B or do I have define B as class method as well?

The problem here isn't that your function is "user-defined", the problem is that "x=B()" does not invoke a method called "B" inside your class, it invokes a method called "B" in the global namespace.

To illustrate what's happening, look at this code:

B="1"

class A():
    B="2"

    def myfunc(cls):
        print B

a = A()
a.myfunc()

If you run that you'll see that the output is 1 .

If you change the print statement to print AB you'll get 2 .

In your case you need to call AB() rather than simply B()

However, as others have pointed out, B() is an instance method. It expects the first parameter it's passed to be an instance of the class. Depending on what B does, it's likely that you're going to have problems caused by the fact that you don't have an instance to pass it. You can work around this in various ways by passing it some other object (such as the class itself), or by creating a new object to pass in; but to me it seems that if C() needs to call an instance method, C() should be an instance method itself.

Difference between Class and Instance methods talks about the difference between class and instance methods.

class methods are methods that don't need instance data. If B needs instance data as implied by using self , then A should not be a class method. If B doesn't need instance data, you can define it to be a class method and call it using cls.B().

To make this work, you need to do something like this:

class A():

    def B(self):
        #do something (with self! so this requires A to be instantiated!)
        return something

    @classmethod
    def C(cls):
        #do something
        return cls().B() #instantiate class, call B method, and return results 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM