2

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?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
macchiavalley
  • 517
  • 1
  • 5
  • 12
  • 1
    It's an *instance* method. How are you going to call it without an instance? If you have an instance, on the other hand (perhaps you created one during `do something`, or you get from some other source) it's trivial. –  Jul 11 '14 at 22:19
  • 1
    Somebody needs to merge those tags into synonyms. –  Jul 11 '14 at 22:22
  • By the definition in your code, B is a member of `A` and takes a single argument (`self`). And if `x` is an `A` object, then `x.B()` is just syntactic sugar for `A.B(x)`. So you need to reference your function by the containing class and pass in the right number of arguments. – murgatroid99 Jul 11 '14 at 22:24

3 Answers3

1

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 A.B you'll get 2.

In your case you need to call A.B() 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.

Community
  • 1
  • 1
James Polley
  • 7,977
  • 2
  • 29
  • 33
0

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

tdelaney
  • 73,364
  • 6
  • 83
  • 116
0

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 
Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331