本文摘自php中文网,作者黄舟,侵删。
本文通过实例给大家详细解释了Python 的类、继承和多态的定义和用法,非常实用,有需要的小伙伴可以参考下类的定义
假如要定义一个类 Point,表示二维的坐标点:
1 2 3 4 | class Point:
def init( self , x = 0 , y = 0 ):
self .x, self .y = x, y
|
最最基本的就是 init 方法,相当于 C++ / Java 的构造函数。带双下划线 的方法都是特殊方法,除了 init 还有很多,后面会有介绍。
参数 self 相当于 C++ 的 this,表示当前实例,所有方法都有这个参数,但是调用时并不需要指定。
1 2 3 4 5 6 | >>> from point import *
>>> p = Point( 10 , 10 )
>>> type (p)
< class 'point.Point' >
>>> p.x, p.y
( 10 , 10 )
|
几乎所有的特殊方法(包括 init)都是隐式调用的(不直接调用)。
对一切皆对象的 Python 来说,类自己当然也是对象:
1 2 3 4 5 6 | >>> type (Point)
< class 'type' >
>>> dir (Point)
[ 'class' , 'delattr' , 'dict' , ..., 'init' , ...]
>>> Point. class
< class 'type' >
|
Point 是 type 的一个实例,这和 p 是 Point 的一个实例是一回事。
现添加方法 set:
1 2 3 4 | class Point:
...
def set ( self , x, y):
self .x, self .y = x, y
|
1 2 3 4 | >>> p = Point( 10 , 10 )
>>> p. set ( 0 , 0 )
>>> p.x, p.y
( 0 , 0 )
|
p.set(...) 其实只是一个语法糖,你也可以写成 Point.set(p, ...),这样就能明显看出 p 就是 self 参数了:
1 2 3 | >>> Point. set (p, 0 , 0 )
>>> p.x, p.y
( 0 , 0 )
|
值得注意的是,self 并不是关键字,甚至可以用其它名字替代,比如 this:
1 2 3 4 | class Point:
...
def set (this, x, y):
this.x, this.y = x, y
|
与 C++ 不同的是,“成员变量”必须要加 self. 前缀,否则就变成类的属性(相当于 C++ 静态成员),而不是对象的属性了。
访问控制
Python 没有 public / protected / private 这样的访问控制,如果你非要表示“私有”,习惯是加双下划线前缀。
1 2 3 4 5 6 7 8 9 | class Point:
def init( self , x = 0 , y = 0 ):
self .x, self .y = x, y
def set ( self , x, y):
self .x, self .y = x, y
def f( self ):
pass
|
x、y 和 f 就相当于私有了:
1 2 3 4 5 6 7 | >>> p = Point( 10 , 10 )
>>> p.x
...
AttributeError: 'Point' object has no attribute 'x'
>>> p.f()
...
AttributeError: 'Point' object has no attribute 'f'
|
_repr_
尝试打印 Point 实例:
1 2 3 | >>> p = Point( 10 , 10 )
>>> p
<point.Point object at 0x000000000272AA20 >
|
通常,这并不是我们想要的输出,我们想要的是:
添加特殊方法 repr 即可实现:
1 2 3 | class Point:
def repr ( self ):
return 'Point({}, {})' . format ( self .x, self .y)
|
不难看出,交互模式在打印 p 时其实是调用了 repr(p):
>>> repr(p)
'Point(10, 10)'
_str_
如果没有提供 str,str() 缺省使用 repr() 的结果。
这两者都是对象的字符串形式的表示,但还是有点差别的。简单来说,repr() 的结果面向的是解释器,通常都是合法的 Python 代码,比如 Point(10, 10);而 str() 的结果面向用户,更简洁,比如 (10, 10)。
按照这个原则,我们为 Point 提供 str 的定义如下:
1 2 3 | class Point:
def str ( self ):
return '({}, {})' . format ( self .x, self .y)
|
_add_
两个坐标点相加是个很合理的需求。
1 2 3 4 5 6 | >>> p1 = Point( 10 , 10 )
>>> p2 = Point( 10 , 10 )
>>> p3 = p1 + p2
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: unsupported operand type (s) for + : 'Point' and 'Point'
|
添加特殊方法 add 即可做到:
1 2 3 | class Point:
def add( self , other):
return Point( self .x + other.x, self .y + other.y)
|
1 2 3 | >>> p3 = p1 + p2
>>> p3
Point( 20 , 20 )
|
这就像 C++ 里的操作符重载一样。
Python 的内建类型,比如字符串、列表,都“重载”了 + 操作符。
特殊方法还有很多,这里就不逐一介绍了。
继承
举一个教科书中最常见的例子。Circle 和 Rectangle 继承自 Shape,不同的图形,面积(area)计算方式不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Shape:
def area( self ):
return 0.0
class Circle(Shape):
def init( self , r = 0.0 ):
self .r = r
def area( self ):
return math.pi * self .r * self .r
class Rectangle(Shape):
def init( self , a, b):
self .a, self .b = a, b
def area( self ):
return self .a * self .b
|
用法比较直接:
1 2 3 4 5 6 7 | >>> from shape import *
>>> circle = Circle( 3.0 )
>>> circle.area()
28.274333882308138
>>> rectangle = Rectangle( 2.0 , 3.0 )
>>> rectangle.area()
6.0
|
如果 Circle 没有定义自己的 area:
1 2 | class Circle(Shape):
pass
|
那么它将继承父类 Shape 的 area:
1 2 | >>> Shape.area is Circle.area
True
|
一旦 Circle 定义了自己的 area,从 Shape 继承而来的那个 area 就被重写(overwrite)了:
1 2 3 | >>> from shape import *
>>> Shape.area is Circle.area
False
|
通过类的字典更能明显地看清这一点:
1 2 3 4 | >>> Shape. dict [ 'area' ]
<function Shape.area at 0x0000000001FDB9D8 >
>>> Circle. dict [ 'area' ]
<function Circle.area at 0x0000000001FDBB70 >
|
所以,子类重写父类的方法,其实只是把相同的属性名绑定到了不同的函数对象。可见 Python 是没有覆写(override)的概念的。
同理,即使 Shape 没有定义 area 也是可以的,Shape 作为“接口”,并不能得到语法的保证。
甚至可以动态的添加方法:
1 2 3 4 5 6 7 | class Circle(Shape):
...
Circle.area = lambda self : math.pi * self .r * self .r
|
动态语言一般都是这么灵活,Python 也不例外。
Python 官方教程「9. Classes」第一句就是:
相关阅读 >>
配置Python连接oracle,读取excel数据写入数据库
Python中一些常用模块的介绍
Python必学知识点总汇
Python编程时如何添加中文注释
Python中类的创建与使用详解
Python中如何合并两个字典教程
Python怎么输出分数形式
Python是什么意思?怎么读?
Python虚拟茶话会效果
Python中all()函数和any()函数的便捷用法
更多相关阅读请进入《Python》频道 >>
人民邮电出版社
python入门书籍,非常畅销,超高好评,python官方公认好书。
转载请注明出处:木庄网络博客 » Python中关于类和继承以及多态的示例详解