Indradhanush Gupta
Indradhanush Gupta

Reputation: 4237

How to call a method of a class from another class?

I want to call a method of a class from another class. I'd like to do something like this.

class A:
    def meth(self):
        B.meth1()

class B:
    def meth1(self):
        pass

a = A()
a.meth()

I get the following error :

TypeError: unbound method meth1() must be called with B instance as first argument (got nothing instead)

What am I doing wrong?

Update:

The example above is probably a bit vague. Here's what I exactly intend to do :

class A:
    def meth(self, data):
        if data[0] == '/':
            B.handleCOMMAND(data)

class B:
    def handleCOMMAND(self, data):
        """
        Some code to handle some command.
        """

Update 2:

class A:
    def meth(self, data):
        if data[0] == '/':
            B.handleCOMMAND(data)

class B:
    def __init__(self):
        self.state = 'CHAT'

    def handleCOMMAND(self, data):
        if data.strip().split()[1] == 'send':
             self.state == 'RECV-FILE'

The main problem I am facing is that :

'self.state' is an instance variable in class B. And depending on what 'data' meth() of class A gets, handleCOMMAND of class B needs to be invoked which is supposed to alter the value of 'self.state'

Upvotes: 0

Views: 360

Answers (4)

abarnert
abarnert

Reputation: 365717

You can't call an instance method unless you have an instance to call it on.

Without knowing what your design goals are, it's impossible to tell you where the instance should come from, but there are two particularly common patterns.

First, the method might take a B instance as a parameter. For example:

class A:
    def meth(self, b):
        b.meth1()

class B:
    def meth1(self):
        pass

a = A()
b = B()
a.meth(b)

To make this more concrete, imagine that A is a Car, and B is a TollRoad, and my_car.drive(my_road) has to call my_road.pay_toll().


Alternatively, each A instance may own a B instance as a member. For example:

class A:
    def __init__(self, b):
        self.b = b
    def meth(self):
        self.b.meth1()

class B:
    def meth1(self):
        pass

b = B()   
a = A(b)
a.meth()

To make this more concrete, imagine that A is a Car again, and B is a ServiceCenter, and my_car.schedule_service() needs to call my_car.service_center.get_next_appointment().


As a variation to the latter, each B instance may be a sort of part-of-the-whole of an A instance, constructed automatically by the A instance. For example:

class A:
    def __init__(self):
        self.b = B()
    def meth(self):
        self.b.meth1()

class B:
    def meth1(self):
        pass

a = A()
a.meth()

For this one, imagine that A is a Car again, and B is an Engine. So, my_car.drive() starts off calling my_car.engine.start(). But, unlike a ServiceCenter, which is a thing that lives on its own and is used by many cars, an Engine is only used by the car it's part of, so there's no good reason to create the engine separately and pass it to the car (unless you're modeling a car factory).

Upvotes: 4

Captain Skyhawk
Captain Skyhawk

Reputation: 3500

B is being used as a static class.

class A:
    def meth(self):
        B.meth1()

class B:
    @staticmethod
    def meth1():
        pass

a = A()
a.meth()

Upvotes: 1

Jeffrey Froman
Jeffrey Froman

Reputation: 6623

Here B.meth1 is an instance method, and you are attempting to use it as a class method. You can either re-define B.meth1 to be a classmethod:

class B:
  @classmethod
  def meth1(cls):
    pass

Or, you can call it as an instance method by instantiating the B class:

class A:
    def meth(self):
        B().meth1()

Upvotes: 0

hek2mgl
hek2mgl

Reputation: 157990

class A:
    def meth(self):
        "create instance of B class"
        b = B()
        b.meth1()

Also you can declare B.meth1() as static:

class B:
    @staticmethod
    def meth1():
        pass

Then you can call it like this:

class A:
    def meth(self):
        "create instance of B class"
        B.meth1()

Upvotes: 0

Related Questions