|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 和vvv 于 2017-11-18 15:22 编辑
01 初探__init__()方法
通过重写特殊方法来完成Python内部机制的调用,在Python中是很普遍的。例如len()函数就可以重写一个类的__len__()方法。这意味着对于像__len__()这样的通用公共接口,任何类都可以实现它。任何一个类都可以重写一个像__len__()这样的特殊方法,这样一种机制构成了Python多态机制的一部分。任何实现了__len__()函数的类都会响应通用公共接口len(x)中的len()函数。
(1)隐式的基类-object
每个Python类的定义都会隐式继承自object类,它的定义非常简单,几乎什么行为都不包括。我们可以创建一个object实例,但很多事情无法完成,因为很多特殊方法的调用程序都会抛出异常。
现在来看看例子:- class Student:
- def hello(self):
- print('hello')
复制代码 然后我们这样:- #判断Student的类别,相当于函数type()
- Student.__class__
复制代码 结果:说明Student是一个类。这样也可以:结果:我们来看看Student类是否还有父类,用什么方法呢?为了判断object是不是Student的父类,我们可以使用issubclass()方法:- issubclass(Student,object)
复制代码 结果:说明Student是object的子类。我们也可以这样:或者:- Student.__class__.__base__
复制代码 结果都是:相应地,派生自object类中的对象方法也将继承各自相应的默认实现。在某些情况下,基类中一些特殊方法的默认行为也正是我们所需要的。但是呢,人难免有需求,这时我们就需要重写这些方法了。
(2)基类中的__init__()方法
对象的生命周期:
object作为所有类的基类,已经为__init__()方法提供了默认实现。一般来说,我们不需要重写这个函数。这时,在创建对象时将不会产生其他变量的实例。
对于继承自object的子类,总可以对它的属性进行扩展。- class Rectangle:
- def area(self):
- return self.width * self.length
复制代码 匆匆地瞄一眼,感觉这段代码有点问题,width和length是从哪里冒出来的。 但运行之后,并没有报错。再好好地想了想,应该是这样的。Python的变量不需要事先声明,直接使用就可以了。上面的类不就是这样的嘛!self.width代表width是本类的属性。只是,我们没有对width和length进行初始化。
看这样是否有问题:想想,
看看:- ---------------------------------------------------------------------------
- AttributeError Traceback (most recent call last)
- <ipython-input-10-848c6814f3c7> in <module>()
- 1 r = Rectangle()
- ----> 2 r.area()
- <ipython-input-8-9390a30b29ca> in area(self)
- 1 class Rectangle:
- 2 def area(self):
- ----> 3 return self.width * self.length
- AttributeError: 'Rectangle' object has no attribute 'width'
复制代码 果然出现问题了。原来如此,width和height根本无实际意义,只是一个标签。就相当于你直接在>>>直接输入a,你看它会不会报错。因此,我们要先让其能够width和length成为变量(变量包括变量名和变量值),才行。- r = Rectangle()
- r.width = 5
- r.length = 6
- r.area()
复制代码 结果:现在,就可以了。
虽然这种延迟赋值的实现方式在Python中是合法的,但是却给调用者带来了潜在的困惑,因此要尽量避免这样的方法。那我们怎样来为类进行初始化呢?这时,我们就需要重写基类的__init__()方法了。
(3)在基类中实现__init__()方法
通过实现__init__()方法来初始化一个对象。每当创建一个对象时,Python将会先创建一个空对象,然后调用该对象的__init__()函数。
__init__()方法提供了对象内部变量以及其他一些一次性过程的初始化操作。
现在呢,来看看一个例子:- class Card:
- def __init__( self, rank, suit ):
- self.suit = suit
- self.rank = rank
- self.hard, self.soft = self._points()
- class NumberCard( Card ):
- def _points( self ):
- return int(self.rank), int(self.rank)
-
- class AceCard( Card ):
- def _points( self ):
- return 1, 11
- class FaceCard( Card ):
- def _points( self ):
- return 10, 10
复制代码 在基类中,我们对suit和rank进行了初始化,我们可以这样使用:- c = Card('A','黑桃')
- print( c.rank, c.suit, c.hard, c.soft )
复制代码 结果:A 黑桃 0 0
- n = NumberCard('5','红桃')
- print( n.rank, n.suit, n.hard, n.soft)
复制代码 结果:5 红桃 5 5
- a = AceCard('6','方块')
- print( a.rank, a.suit, a.hard, a.soft)
复制代码 结果:6 方块 1 11
- f = FaceCard('6','方块')
- print( f.rank, f.suit, f.hard, f.soft)
复制代码 结果:6 方块 10 10
这里一个常见的多态设计,每个子类为_points()方法提供特有的功能。所有的子类拥有相同的方法名和属性。
今天就到这里了。
|
|