关于 TypeError 和 AttributeError with 类 的解释

Explanation about TypeError and AttributeError with classes

我对 python 不是很陌生,在最后两个项目中使用了 classes,但是有两个概念对我来说不是很清楚。 我正在编写一个编译器,我的代码有 1K+ 行,所以我编写了一个简单的代码来总结我遇到的两个我不明白的错误:

class A:
    def __init__(self):
        self.var = 15

    def methodA(self):
        self.var = 0

class B:
    def __init__(self):
        self.a = A()

    def methodB(self):
        self.a.methodA()

    def run(self):
        self.methodB()

B.run()

我得到的错误是:

AttributeError: type object 'B' has no attribute 'a'

TypeError: run() missing 1 required positional argument: 'self'

我知道我可以按如下方式修复代码

class A:
    def __init__(self):
        self.var = 15

    def methodA(self):
        self.var = 0

class B:
    def __init__(self):
        pass

    def methodB(self):
        A.methodA(A)

    def run(self):
        B.methodB(B)

A.__init__(A)
B.run(B)

但我不明白为什么我不能创建 A class 实例作为 B 属性,为什么我不能使用 self.method 而不是B.method(B).

您正在使用 class 调用方法,而不是对象。你需要这样称呼它:

B().run()

不要混淆 BB()。一个是 B 的元 class 的实例,即 class 而第二个是 class B 的实例。由于该方法未声明为 classmethod,您需要 class B 的实例才能调用它。

您的第二个代码片段有效,因为在执行 A.__init__(A) 时,您基本上添加了一个 class 属性 A.var = 15。当您调用 B.run(B) 时,您基本上会执行 A.method(A),它只是设置 A.var = 0(您之前设置为 15)。您在这里混淆了 classes 和实例,但它仍然有效,因为最终两者本质上都是对象。

例如,从这里

>>> class A:
...     def f(self):
...         print(1)
>>> A().f
<bound method A.f of <__main__.A object at 0x10b641b50>>
>>> A.f
<function A.f at 0x10b759c10>

第一种情况清楚地表明它是 A 实例的绑定方法,在使用 A() 调用时不需要参数,而在第二种情况下,A.f 不被视为一种方法,而是一种函数,它需要一个参数才能被调用。所以你可以用任何方式调用它,就像一个接受一个绝对参数的普通函数(只要你不在里面做类似 print(self.some_attribute)self.some_attribute = some_val 的事情):

>>> A.f(123123)
1
>>> A.f(33234)
1