关于 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()
不要混淆 B
和 B()
。一个是 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
我对 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()
不要混淆 B
和 B()
。一个是 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