140
如果没有这个方法,Python会求其长度,因为一个非空对象看作是真。
>>> class Truth:
def __len__(self):return 0
>>> x=Truth()
>>> if not x:print('no')
no
如果两个方法都有,Python会调用__bool__,因为它更加具体:
>>> class Truth:
def __bool__(self):return True
def __len__(self):return 0
>>> x=Truth()
>>> if x:print('yes')
网页设计html代码大全继承关系
yes
如果没有定义真的方法,对象看作真:
>>> class Truth:
pass
>>> x=Truth()
>>> bool(x)
True
作为一名类的设计者,你可以选择使用或不使用运算重载符。你的抉择取决于有多想让对象的用法和外观看起来更像内置类型。如果省略运算符重载方法,并且不从超类中继承该方法,实例就不支持相应的运算;如果试着使用这个实例进行运算,就会抛出异常(或者使用标准的默认值)。坦白地讲,只有在实现本质为数学的对象时,才会用到许多运算符重载方法。例如,向量或矩阵类可以重载加法运算符,但员工类可能就不用。就较简单的类而言,可能根本就不会用到重载,而应该利用明确的方法调用来实现对象的行为。
几乎每个实际的类似乎都会出现的一个重载方法是:__init__构造函数。因为这可让类立即在其新建的实例内添加属性,对于每种你可能会写的类而言,构造函数都是有用的。事实上,虽然Python不会对实例的属性进行声明,但通常也可以通过到类的__init__方法的代码而了解实例有哪些属性。
6.7 继承
面向对象编程具有三个特性—封装性、多态性、继承性。继承是为代码重用而设计的,当我们设计一个新类时,为了代码重用可以继承一个已设计好的类。在继承关系中,原来设计好的类称为父类,新设计的类称为子类。继承允许基于类的特点创建另一个类,完成这个步骤需要两个步骤。首先,在类上增加关联,类似于实例和类之间的关联。其次,这种关联关系能够“继承”位于关系方案上层的类的属性。通过继承这些属性,可以实现代码共享。
141 在Python 中,当对对象进行点号运算时,就会发生继承,而且涉及了搜索属性定义树(一个或多个命名空间)。每次使用object.attr 形式的表达式时(object 是实例或类对象),python 会从头至尾搜索命名空间树,先从对象开始,寻所能到的第一个attr 。这包括在方法中对self 属性的引用。因为树中较低的定义会覆盖较高的定义,继承构成了专有化的基础。
子类继承父类时用class 子类名(父类名)来表示。子类能继承父类的所有公有成员。在需要的时候,在子类中可通过super()来调用父类的构造函数,也可通过父类名来调用父类的构造函数。
1.属性树的构造
图6-2总结了命名空间树构造以及填入变量名的方法。
● 实例属性是由对方法内self 属性进行赋值运算而生成的。
● 类属性是通过class 语句内的语句(赋值语句)而生成的。
● 超类的连接是通过class 语句首行的括号内列出类而生成的。
图6-2  命名空间树及填入变量名的方法
图6-2对应的程序代码会在内存中创建对象树,这个树是通过属性继承搜索的。调用类会创建记忆了这个类的新的实例。执行class 语句会创建新的类,而列在class 语句首行括号内的类则成为超类。self 属性位于类的方法内每个属性引用,都会触发由下至上的树搜索。
结果就是连接实例的属性命名空间树,到产生它的类、再到类首行中所列出的所有超类。每次以点号运算从实例对象取出属性名称时,Python 会向上搜索树,从实例直到超类。
2.继承方法的专业化
上文谈到了继承树搜索模式,是将系统专有化的最好方法。因为继承会先在子类寻变量名,然后才查超类,子类就可以对超类的属性重新定义来取代默认的行为。实际上,你可以把整个系统做出类的层次,再新增外部的子类来对其进行扩展,而不是在原处修改已经存在的逻辑。
重新定义继承变量名的概念引出了各种专有化技术。例如,子类可以完全取代继承的属性,提供超类可以到的属性,并且通过已覆盖的方法回调超类来扩展超类的方法。我们已经看到过实际中取代的做法。下面是如何扩展的例子。
>>> class Super:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。