给个知乎的连接吧,知乎的例子说的应该是:
设计模式六大原则之一:迪米特法则,一个对象应该对其他对象保持最少的了解。如果类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
# 任务1
class Person():
def __init__(self, x, y):
self._x = x
self._y = y
def math(self): return self._x + self._y
# 任务2
P1 = Person(5, 6)
print(P1.math())
# 分割线 ===================================================
# 任务1
class Person():
def math(self): return self._x + self._y
# 任务2
P1 = Person()
P1._x = 5
P2._y = 6
print(P1.math())
两个人合作,每人完成一个任务。前者的完成任务2的人,不需要知道Person的内部属性,但是后者需要两人事先约定Person的内部属性。所有代码相关代码写到一块,由一个人维护,要比两个人共同维护好。对于第二种写法,如果有一天完成任务1的人把math改成了def math(self): self._z + self._y,如果他没有通知完成任务2的人,那么整个程序将会挂掉。而如果写到了一起,那么由一个人维护,他就会把两处都改了,另一个人不需要做任何额外的修改。所以如果要写成后者,我们更愿意写成,完成任务1的人生成一个会计算加法的Person,而完成任务2的人使用Person计算了5+6:
# 任务1
class Person():
def math(self, x, y):
return x+y
# 任务2
P1 = Person()
print(P1.math(5, 6))
所以,你给的两种写法都可以,只是他们留了不同的接口。至于那种更好么,应用场景决定(如何选择就是能不能写出优秀代码的难点)。
除了编译器提供的内置类型,我们还可以自定义类型。为了构造自己的类型,我们需要自己给出自定义类型的定义以及如何创建和初始化这个类型。“构造函数”就给出了如何创建以及初始化这个类型。Python是弱类型,所有对象构造方法一样,只是初始化不一样,所以这个函数叫做init。这个__init__就是一个“构造函数”!这个函数在创建对象的时候由编译器自动调用,并且编译器会忽略他的返回值。其实真正的构造函数是__new__,由__new__创建对象,然后把这个对象当做self传递给__init__,所以__init__不需要返回值。
从另一个角度来说,构造函数的作用是:类型转换, 类型转换, 类型转换。第一个Person可以把tuple类(x,y)转换成了一个只会计算x+y的Person。而第二种写法把()转换成了一个会计算加法的Person--因为遵循了迪米特法则,一句话搞定而不是解释半天。
在其他一些语言里,构造函数是与类名相同的一个函数。这些语言里更容易理解P1 = Person(5,6)里的Person更多的是一个函数,而不是一个类名。只是这个函数名与类名重名而已。Python里的__init__就是构造函数完成初始化对象的那一部分,它的参数就是所有构造函数的参数+已经构造出的对象。