Python:将class方法赋值给一个变量

Python: Assigning class method to a variable

我在 class 中有很多方法,我需要调用一个特定的方法。我试过这样的东西,但得到了一个 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()

我希望下面的东西能起作用,但我遇到了这个异常:

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

那么有什么办法吗?

class 中的函数定义应包含 'self' 作为参数

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

我们应该在这里讨论几件事。我将尝试解释不同的场景,让您大致了解发生了什么。

首先让我们看看你的最后一行:

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

您正在尝试从实例 my_obj 获取 first_func 属性。它(或者它是class)有那个吗? 没有
first_func 是全局模块中的一个变量。 my_obj对此一无所知。

所以你的异常是因为这个...


现在考虑你的方法:
firstsecond 方法是 class 中的常规方法。当您说 MyClass.first 时,您得到的是函数对象 而不是方法 。此函数接受两个参数 ab.

但是如果你说 my_obj.first_func 你会得到一个 方法对象 它有一个绑定的实例对象。 Python 使用对调用此方法的实例的引用为您填充第一个参数。现在你的方法对象只接受一个参数b。 (这就是描述符的工作原理)

话虽如此,您在这里有一些选择:

1 - 仅从 class 而不是实例调用它们:

否则你会得到异常,因为Python已经用实例对象填充了第一个参数。

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- 用 staticmethod:

装饰它们

现在您可以从实例调用或 class,Python 不会为您填充第一个参数。

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- 添加一个self参数(它的名称不是规则而是强烈推荐的约定):

这一次,如果您从实例中调用它们,则不需要将实例传递给第一个参数,但如果您从 class 中调用它们,则需要将其作为第一个参数传递。

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