为什么在Pythonclass__init__里面调用函数既可以是Attribute又可以是Method?

Why calling a function inside a Python class __init__ can be both Attribute and Method?

我对 Python class 的 方法 属性 感到很困惑。假设我们有一个 Python class 这样的:

# case 1
class Person:

    def __init__(self, first, last):

        self.first = first
        self.last = last
        self.fun()

    def fun(self):
        value = self.first + '---' + self.last
        self.fun = value
        return value

person_1 = Person('A', 'B')  
person_1.fun

---> "A---B"

我们可以看到,在case_1中我们初始化了一个实例person_1。而我们可以通过调用fun作为属性来得到我们想要的结果。但是,如果我们将代码更改为以下内容,fun 将变为 方法 (case_2)

# case 2
class Person:

    def __init__(self, first, last):

        self.first = first
        self.last = last
        self.fun()

    def fun(self):
        value = self.first + '---' + self.last
        return value

person_1 = Person('A', 'B')  
person_1.fun

---> <bound method Person.fun of <__main__.Person object at 0x7fd4f79168d0>>

我们仍然在 class 中包含 init 进程。但是现在 fun 变成了 方法 而不是 属性 (case_2)

如果我们删除init中的self.fun()但保留self.fun = value,它仍然是方法(case_3)

# case 3
class Person:

    def __init__(self, first, last):

        self.first = first
        self.last = last

    def fun(self):
        value = self.first + '---' + self.last
        self.fun = value
        return value

person_1 = Person('A', 'B')  
person_1.fun

---> <bound method Person.fun of <__main__.Person object at 0x7fd4f797f390>>

你介意告诉我一些关于为什么会发生这种情况的说明吗?将函数用作 Python Class 中的属性的正确方法是什么?提前致谢!

啊哈,我想我明白了!

在情况 1 中,我们在初始化实例时简单地 运行 函数 fun()。并且因为它在fun() 中定义了属性self.fun = value,因此fun 可以用作属性。 (它不能再用作方法,因为它已被替换为属性。)

情况2,我们只调用和运行这个函数。但是 fun 没有被定义为 class 里面的属性。这就是为什么它仍然作为一种方法。

案例3中,fun是一个方法,但是在这个方法中,我们定义了一个属性fun。因此我们可以先初始化一个实例,然后 运行 函数 fun。之后,属性fun被添加到这个实例,然后我们可以称它为person_1.fun.

在情况 1 中,您的构造函数调用 fun(),其中有一行代码用属性值覆盖自身。这很混乱,也不是一件好事,因为它很混乱。

在情况 2 中,您的 fun 方法不包含覆盖自身的行,因此它不会被覆盖。

在情况 3 中,您实际上从未调用过有趣的方法,因此它永远没有机会覆盖自身。如果你用 person_1.fun() 调用它,即带括号,那么它会执行并覆盖自己,从那时起,person_1.fun 将是一个属性值。

请记住,在 python 中,function/method 仅在使用括号调用时执行。如果不使用括号表示,那么计算结果不是函数的输出,而是表达式产生对函数本身的引用,可以将其放入另一个变量或数据结构中,稍后调用.

为了说明这一点:

>>> def my_func():                                      
...     print('got called')                             
...     return 42                                       
...                                                     
>>> x = my_func #no parentheses, x becomes an alias to my_func                         
>>> y = my_func()  #parentheses means actually execute                                      
got called                                              
>>> y                                                   
42                                                      
>>> x                                                   
<function my_func at 0x765e8afdc0>                      
>>> x()  #x is a reference to my_func and can be called itself                                               
got called                                              
42                                                      
>>>