11,074
社区成员
学习了C++、C#还有JAVA之后,我对面向对象中的类与对象之间关系的理解是这样:类是模板、蓝图,在创建类对象的时候依据的是类,也就是说,可能具体属性值可能不同,但所有由同一个类创建的类对象都具有相同的属性。
在了解Python之前,我一直都是这种理解。但后来,我想到了一段Python代码,如下:
class my_class():
def __init__(self) -> None:
pass
def fun1(self):
self.aaa = 'aaa'
def fun2(self):
self.bbb = 'bbb'
def fun3(self):
print(self.aaa, self.bbb)
c1 = my_class()
#c1.fun3()
c2 = my_class()
c2.fun1()
#c2.fun3()
c3 = my_class()
c3.fun1()
c3.fun2()
c3.fun3()
直接执行这个程序,输入如下:
aaa bbb
如果把#c2.fun3()注释取消后再执行,则程序出错:
Traceback (most recent call last):
File "e:\Project\Python\Learning\hello_world\demo.py", line 19, in <module>
c2.fun3()
File "e:\Project\Python\Learning\hello_world\demo.py", line 12, in fun3
print(self.aaa, self.bbb)
AttributeError: 'my_class' object has no attribute 'bbb'
如果把#c1.fun3()注释取消后再执行,则程序同样会出错:
Traceback (most recent call last):
File "e:\Project\Python\Learning\hello_world\demo.py", line 15, in <module>
c1.fun3()
File "e:\Project\Python\Learning\hello_world\demo.py", line 12, in fun3
print(self.aaa, self.bbb)
AttributeError: 'my_class' object has no attribute 'aaa'
由此看来,c1没有属性'aaa',c2没有属性'bbb',而c3同时具有属性'aaa'和'bbb'。这样的话,均由类'my_class'创建的三个对象,具有属性却都不一样。这有些颠覆我对类及对象的理解。不知是我之前的理解错了,还是说Python语言改变了类及对象的定义?
我另外写了一段代码如下:
import random
class my_class():
def __init__(self) -> None:
pass
def fun1(self):
self.aaa = 'aaa'
def fun2(self):
self.bbb = 'bbb'
def fun3(self):
print(self.aaa, self.bbb)
c1 = my_class()
if random.randint(1, 100) != 100:
c1.fun1()
if random.randint(1, 100) != 100:
c1.fun2()
c1.fun3()
这段代码正确执行的概率是99.99%,但这段代码就是错的。在稍大一点的项目中,只能看到程序报错,很难捕捉这种错误。
其实你没有明白我的意思,我并非是想DEBUG这一段代码使其能够看起来”正常“。我是想表达,用同一个类创建的三个类对象,这三个对象的属性字段都不相同,这还算是同一个类类型吗?一个类的结构竟然要依赖于对象实例对方法的调用顺序,是不是会存在较大的隐患?不可否认,可以通过良好的编码风格来规避这一问题。但这种特性带来的益处是否真的大于其隐藏的风险?对于非常小的项目,这应该不成问题,但如果遇到稍大一点的项目,尤其是依赖程序运行状态而发生的错误很难被捕捉或场景还原。为什么Python不能规避这个问题呢?
class my_class():
def __init__(self) -> None:
self.aaa = 'start'
self.bbb = 'end'
def fun1(self):
self.aaa = 'aaa'
def fun2(self):
self.bbb = 'bbb'
def fun3(self):
print(self.aaa, self.bbb)
在初始化实例的方法里,加上默认值,你再运行你的几个调用,就可以看出区别了
我也刚学python,不知道理解的对不对啊
首先,你的类在实例化时,没有任何属性
aaa也好,bbb也好,都是由实例中的方法创建的,你没有调用相应的方法,那么对应的属性就没有被建立起来,所以会报错