面向对象编程,无需初始化



我读过很多类似的问题,但我仍然不明白。

请看这个例子:

class Cat:
pass
a_cat = Cat
a_cat.name = "hs"
a_cat.name
'hs' #returns this

上面我做了一个cat class的例子,name是专门关于那只猫的。未使用__init __

这是一个类似的例子,但有__init__.

class Dog:
def __init__(self,name):
self.name = name
doggo = Dog("ad")
doggo.name
'ad' #returns this

问题: 如果两个版本都允许将方法传递给每个类的单个实例,那么为什么要费心做第二种方法呢?它们看起来像相同的结果。

不同之处在于 init 方法是在对象初始化时调用的,例如这意味着您需要传递参数。假设你有一个有颜色的类狗,你不能使用没有颜色的狗,所以你需要传递一个颜色,否则依赖于这个颜色的函数将无法运行。 这里也是一个很好的解释链接:https://micropyramid.com/blog/understand-self-and-init-method-in-python-class/

对于 Dog 的示例,假设您有一个函数

print(self.color)

如果不使用颜色初始化类,则函数将不会运行。__init__函数始终在初始化时运行,您可以指定从对象进行初始化时必须传递的参数。指狗 ->颜色。

第一种方法和第二种方法之间的区别在于,在第二种方法的帮助下,您强制新创建的对象在调用其任何方法之前具有一些默认值。

这样,我们可以避免在调用处理没有值的属性的方法时出现错误。

第一种方法的问题在于a_cat没有name属性,除非你分配它。在实用的OOP中(它更像是范式而不是任何特定的语言实现,并且肯定也可以在Python中"正确"完成(,您希望同一类的对象具有相同的"协议" - 属性和方法集 - 这在编写使用这些类的代码时有很大帮助。例如,如果你有使用类Cat的类Vet,那么Vet的程序员在对它做某事之前不需要检查 Cat 的每个实例以查看是否有名称,因为名称是Cat协议的一部分并且始终存在。

在 Python 中,__init__()通常用于确保类的所有实例在实例化时都具有所有必需的属性,因此当他们的Vet类中的某人if cat.name.startswith('A'):AttributeError当该特定Cat实例中未设置属性时name他们不会最终出现异常。

面向对象的编程就是关于封装的。定义对象时,将有关现实世界的一些知识封装到该对象中。

封装就是禁止直接从外部世界操纵对象的内部状态。通过"内部状态的操纵",我的意思是直接修改对象属性,就像您的示例一样:

dog = Dog()
dog.name = 'Spot'

这与OOP试图实现的目标完全相反。

相反,OOP 建立了一个定义良好的模式:在创建对象时初始化具有初始状态的对象。所以,这就是构造函数的来源。为了在创建对象时初始化对象,您需要将一些参数传递给构造函数。

这就是为什么"带参数的构造函数"方法总是比"创建,然后分配属性"方法更可取的原因。更重要的是,在理想世界中,每个对象在创建初始状态后都应该是不可变的,并且只允许查询其状态并禁止更改它。

最新更新