面向对象编程:即使用程序员自己定义的类来组织代码和数据
(一)自定义类
- 程序员自己定义的类称之为类(class);
- 自己定义一个类是比较复杂的,但是它的优势是很明显的;
- 可以在一个类中定义函数和变量;
class Point:
"""
Represents a point in 2-D space.
"""
- 像上面这样创建一个类对象(class object);
>>> Point
<class '__main__.Point'>
由于Point
是定义在顶层的,所以全名是__main__.Point
- 类对象实际上就如同一个创建对象的工厂【所谓万事万物皆对象,在大型的系统中,所有的代码都要是通过创建对象的方式】
# 如果要创建一个点,则可以像调用函数那样调用'Point'
>>> blank = Point()
>>> blank
<__main__.Point object at 0xb7e9d3ac>
- 创建一个新的对象的过程称之为实例化(instantiation),新的对象叫做这个类的实例(instance)
(二)属性
使用点标记法对一个实例进行赋值:
>>> blank.x = 3.0
>>> blank.y = 4.0
一个类中已经命名的一类元素叫做属性(attributes);
下面是一张说明一个对象及其属性的状态图——对象图:
>>> blank.y
4.0
>>> blank.x
3.0
- 可以在任何表达式中使用点标记法:
>>> '(%g, %g)' % (blank.x, blank.y)
'(3.0, 4.0)'
>>> distance = math.sqrt(blank.x**2 + blank.y**2)
>>> distance
5.0
- 实例也可以作为参数进行传递:
def print_point(p):
print('(%g, %g)' % (p.x, p.y))
>>> print_point(blank)
(3.0, 4.0)
- 在这个函数内部,
p
是blank
的别名,所以如果函数修改了p
,blank
也会改变;
(三)定义矩形类
class Rectangle:
"""Represents a rectangle
attributes: width, height, corner
"""
创建一个实例:
box = Rectangle()
box.width = 100.0
box.heighgt = 200.0
box.corner = Point()
box.corner.x = 0.0
box.corner.y = 0.0
(四)实例作为返回值
def find_center(rect):
p = Point()
p.x = rect.corner.x + rect.width/2
p.y = rect.corner.y + rect.height/2
return p
(五)对象是可变的
可以通过给一个对象的属性赋值来改变这个对象的状态:
box.width = box.width + 50
box.height = box.height +100
- 可以编写函数来修改对象:
def grow_rectangle(rect, dwidth, dheight):
rect.width += dwidth
rect.height += dheight
>>> box.width, box.height
(150.0, 300.0)
>>> grow_rectangle(box, 50, 100)
>>> box.width, box.height
(200.0, 400.0)
(六)复制
别名会降低程序的可读性,因为一个地方的改变会对另一个地方产生意料之外的影响;
- 通常,用复制对象的方法取代为对象起别名;如使用
copy
模块:
>>> p1 = Point()
>>> p1.x = 3.0
>>> p1.y = 4.0
>>> import copy
>>> p2 = copy.copy(p1)
#p1和 p2 拥有相同的数据,但是它们并不是同一个 Point 对象。
>>> print_point(p1)
(3, 4)
>>> print_point(p2)
(3, 4)
>>> p1 is p2
False
>>> p1 == p2
False
- 但是,这个复制仅仅复制了
Rectangle
对象,但是并没有复制Point
对象:
>>> box2 = copy.copy(box)
>>> box2 is box
False
>>> box2.corner is box.corner
True
这种复制方式称之为浅复制;
- 实际上很多时候上面的复制方法并不是我们想要的,可以使用
deepcopy
方法:
>>> box3 = copy.deepcopy(box)
>>> box3 is box
False
>>> box3.corner is box.corner
False
(七)调试
- 对象中新的异常:访问不存在的属性
>>> p = Point()
>>> p.x = 3
>>> p.y = 4
>>> p.z
AttributeError: Point instance has no attribute 'z'
- 使用
type
检查一个对象的类型
>>> type(p)
<class '__main__.Point'>
- 使用
isinstance
检查某个对象是不是某个类的实例
>>> isinstance(p, Point)
True
- 使用内置函数
hasattr
检查对象是不是含有某个属性:
>>> hasattr(p, 'x')
True
>>> hasattr(p, 'z')
False
- 使用
try
检查某个对象是不是我们所需要的的属性:
try:
x = p.x
except AttributeError:
x = 0