简体   繁体   中英

Python: Assigning class method to a variable

I have a number of methods in a class and I need to call a specific one. I tried something like this, but got an AttributeError

class MyClass:
    def first(a, b):
        return a + b
    def second(a, b):
        return a * b

a = 2
b = 3

first_func = MyClass.first
second_func = MyClass.second

my_obj = MyClass()

I expect something of a following to work, but I'm getting this exception:

my_obj.first_func(a, b) + my_obj.second_func(a, b) == 11

So is there a way to do it?

There are several things that we should discuss here. I will try to explain different scenarios to give you an overview to see what's going on.

First let's see your last line:

my_obj.first_func(a, b) + my_obj.second_func(a, b)

You are trying to get the first_func attribute from the instance my_obj . Does it(or it's class) have that? No.
first_func is a variable in your global module. my_obj doesn't know anything about it.

So your exception is raised because of this...


Now considering your methods:
first and second methods are regular methods inside your class. When you say MyClass.first , You are getting a function object back not a method . This function accepts two parameters a and b .

But if you say my_obj.first_func you get a method object which has a bound instance object. Python fills the first parameter for you with a reference to the instance that you called this method from. Now your method object only accepts one parameter b . (This is how descriptors work)

With that being said, You have some options here:

1 - call them only from the class not the instance:

otherwise you will get exception because Python already filled the first parameter with the instance object.

class MyClass:
    def first(a, b):
        return a + b

    def second(a, b):
        return a * b

first_func = MyClass.first
second_func = MyClass.second
print(first_func(2, 3) + first_func(2, 3))

2- decorate them with staticmethod :

Now you can call either from instance or class, Python won't fill the first parameter for you.

class MyClass:
    @staticmethod
    def first(a, b):
        return a + b

    @staticmethod
    def second(a, b):
        return a * b

first_func = MyClass.first
second_func = MyClass.second
print(first_func(2, 3) + first_func(2, 3))
class MyClass:
    @staticmethod
    def first(a, b):
        return a + b

    @staticmethod
    def second(a, b):
        return a * b

my_obj = MyClass()
first_func = my_obj.first
second_func = my_obj.second
print(first_func(2, 3) + first_func(2, 3))

3- add a self parameter (it's name is not a rule but a strongly recommended convention):

This time if you call them from instance you don't need to pass the instance to the first parameter, but if you call them from the class you need to pass it as the first parameter.

class MyClass:
    def first(self, a, b):
        return a + b

    def second(self, a, b):
        return a * b


my_obj = MyClass()
first_func = my_obj.first
second_func = my_obj.second
print(first_func(2, 3) + first_func(2, 3))
class MyClass:
    def first(self, a, b):
        return a + b

    def second(self, a, b):
        return a * b


my_obj = MyClass()
first_func = MyClass.first
second_func = MyClass.second
print(first_func(my_obj, 2, 3) + first_func(my_obj, 2, 3))

Function definition in a class should contain 'self' as a param

class MyClass:
    def first(self,a, b):
        return a + b
    def second(self,a, b):
        return a * b

a = 2
b = 3

first_func = MyClass.first
second_func = MyClass.second

my_obj = MyClass()
first_func(my_obj,a, b) + second_func(my_obj,a, b) == 11

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