# Python 教程 15 — 类和对象

```"""This module contains a code example related to
Think Python, 2nd Edition
by Allen Downey
http://thinkpython2.com
"""

from __future__ import print_function, division

class Point:
"""Represents a point in 2-D space.
attributes: x, y
"""

def print_point(p):
"""Print a Point object in human-readable format."""
print('(%g, %g)' % (p.x, p.y))

class Rectangle:
"""Represents a rectangle.
attributes: width, height, corner.
"""

def find_center(rect):
"""Returns a Point at the center of a Rectangle.
rect: Rectangle
returns: new Point
"""
p = Point()
p.x = rect.corner.x + rect.width/2.0
p.y = rect.corner.y + rect.height/2.0
return p

def grow_rectangle(rect, dwidth, dheight):
"""Modifies the Rectangle by adding to its width and height.
rect: Rectangle object.
dwidth: change in width (can be negative).
dheight: change in height (can be negative).
"""
rect.width += dwidth
rect.height += dheight

def main():
blank = Point()
blank.x = 3
blank.y = 4
print('blank', end=' ')
print_point(blank)

box = Rectangle()
box.width = 100.0
box.height = 200.0
box.corner = Point()
box.corner.x = 0.0
box.corner.y = 0.0

center = find_center(box)
print('center', end=' ')
print_point(center)

print(box.width)
print(box.height)
print('grow')
grow_rectangle(box, 50, 100)
print(box.width)
print(box.height)

if __name__ == '__main__':
main()```

## 1.程序员自定义类型 #

• 我们可以将坐标存储在两个独立的变量，x和y中。
• 我们可以将坐标作为一个列表或者元组的元素存储。
• 我们可以创建一个新类型将点表示为对象。

```class Point:
"""Represents a point in 2-D space."""```

```>>> Point
<class '__main__.Point'>```

```>>> blank = Point()
>>> blank
<__main__.Point object at 0xb7e9d3ac>```

## 2.属性 #

```>>> blank.x = 3.0
>>> blank.y = 4.0```

```>>> blank.y
4.0
>>> x = blank.x
>>> 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` 作为参数传递：

```>>> print_point(blank)
(3.0, 4.0)```

```from __future__ import print_function, division

import copy
import math

from Point1 import Point, Rectangle

def distance_between_points(p1, p2):
"""Computes the distance between two Point objects.
p1: Point
p2: Point
returns: float
"""
dx = p1.x - p2.x
dy = p1.y - p2.y
dist = math.sqrt(dx**2 + dy**2)
return dist
```

## 3.矩形 #

• 你可以指定矩形的一个角（或是中心）、宽度以及长度。
• 你可以指定对角线上的两个角。

```class Rectangle:
"""Represents a rectangle.

attributes: width, height, corner.
"""```

```box = Rectangle()
box.width = 100.0
box.height = 200.0
box.corner = Point()
box.corner.x = 0.0
box.corner.y = 0.0```

## 4.实例作为返回值 #

```def find_center(rect):
p = Point()
p.x = rect.corner.x + rect.width/2
p.y = rect.corner.y + rect.height/2
return p```

```>>> center = find_center(box)
>>> print_point(center)
(50, 100)```

## 5.对象是可变的 #

```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)```

```def move_rectangle(rect, dx, dy):
"""Move the Rectangle by modifying its corner object.
rect: Rectangle object.
dx: change in x coordinate (can be negative).
dy: change in y coordinate (can be negative).
"""
rect.corner.x += dx
rect.corner.y += dy```

## 6.复制 #

```>>> 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```

```>>> box2 = copy.copy(box)
>>> box2 is box
False
>>> box2.corner is box.corner
True```

```>>> box3 = copy.deepcopy(box)
>>> box3 is box
False
>>> box3.corner is box.corner
False```

`box3`和 `box` 是完全互不相干的对象。

```def move_rectangle_copy(rect, dx, dy):
"""Move the Rectangle and return a new Rectangle object.
rect: Rectangle object.
dx: change in x coordinate (can be negative).
dy: change in y coordinate (can be negative).
returns: new Rectangle
"""
new = copy.deepcopy(rect)
move_rectangle(new, dx, dy)
return new```
```"""This module contains a code example related to
Think Python, 2nd Edition
by Allen Downey
http://thinkpython2.com
"""

from __future__ import print_function, division

import copy
import math

from Point1 import Point, Rectangle

def distance_between_points(p1, p2):
"""Computes the distance between two Point objects.
p1: Point
p2: Point
returns: float
"""
dx = p1.x - p2.x
dy = p1.y - p2.y
dist = math.sqrt(dx**2 + dy**2)
return dist

def move_rectangle(rect, dx, dy):
"""Move the Rectangle by modifying its corner object.
rect: Rectangle object.
dx: change in x coordinate (can be negative).
dy: change in y coordinate (can be negative).
"""
rect.corner.x += dx
rect.corner.y += dy

def move_rectangle_copy(rect, dx, dy):
"""Move the Rectangle and return a new Rectangle object.
rect: Rectangle object.
dx: change in x coordinate (can be negative).
dy: change in y coordinate (can be negative).
returns: new Rectangle
"""
new = copy.deepcopy(rect)
move_rectangle(new, dx, dy)
return new

def main():
blank = Point()
blank.x = 0
blank.y = 0

grosse = Point()
grosse.x = 3
grosse.y = 4

print('distance', end=' ')
print(distance_between_points(grosse, blank))

box = Rectangle()
box.width = 100.0
box.height = 200.0
box.corner = Point()
box.corner.x = 50.0
box.corner.y = 50.0

print(box.corner.x)
print(box.corner.y)
print('move')
move_rectangle(box, 50, 100)
print(box.corner.x)
print(box.corner.y)

new_box = move_rectangle_copy(box, 50, 100)
print(new_box.corner.x)
print(new_box.corner.y)

if __name__ == '__main__':
main()```

## 7.调试 #

```>>> p = Point()
>>> p.x = 3
>>> p.y = 4
>>> p.z
AttributeError: Point instance has no attribute 'z'```

```>>> type(p)
<class '__main__.Point'>```

```>>> isinstance(p, Point)
True```

```>>> hasattr(p, 'x')
True
>>> hasattr(p, 'z')
False```

```try:
x = p.x
except AttributeError:
x = 0```

## 9.练习题 #

### 习题 15-4 #

```"""This module contains a code example related to
Think Python, 2nd Edition
by Allen Downey
http://thinkpython2.com
"""

from __future__ import print_function, division

import copy

from Point1 import Point, Rectangle, print_point
from Point1_soln import distance_between_points

class Circle:
"""Represents a circle.
"""

def point_in_circle(point, circle):
"""Checks whether a point lies inside a circle (or on the boundary).
point: Point object
circle: Circle object
"""
d = distance_between_points(point, circle.center)
print(d)

def rect_in_circle(rect, circle):
"""Checks whether the corners of a rect fall in/on a circle.
rect: Rectangle object
circle: Circle object
"""
p = copy.copy(rect.corner)
print_point(p)
if not point_in_circle(p, circle):
return False

p.x += rect.width
print_point(p)
if not point_in_circle(p, circle):
return False

p.y -= rect.height
print_point(p)
if not point_in_circle(p, circle):
return False

p.x -= rect.width
print_point(p)
if not point_in_circle(p, circle):
return False

return True

def rect_circle_overlap(rect, circle):
"""Checks whether any corners of a rect fall in/on a circle.
rect: Rectangle object
circle: Circle object
"""
p = copy.copy(rect.corner)
print_point(p)
if point_in_circle(p, circle):
return True

p.x += rect.width
print_point(p)
if point_in_circle(p, circle):
return True

p.y -= rect.height
print_point(p)
if point_in_circle(p, circle):
return True

p.x -= rect.width
print_point(p)
if point_in_circle(p, circle):
return True

return False

def main():
box = Rectangle()
box.width = 100.0
box.height = 200.0
box.corner = Point()
box.corner.x = 50.0
box.corner.y = 50.0

print(box.corner.x)
print(box.corner.y)

circle = Circle
circle.center = Point()
circle.center.x = 150.0
circle.center.y = 100.0

print(circle.center.x)
print(circle.center.y)

print(point_in_circle(box.corner, circle))
print(rect_in_circle(box, circle))
print(rect_circle_overlap(box, circle))

if __name__ == '__main__':
main()```

### 习题 15-6 #

```"""This module contains a code example related to
Think Python, 2nd Edition
by Allen Downey
http://thinkpython2.com
"""

from __future__ import print_function, division

import turtle

from Point1 import Point, Rectangle
from Circle import Circle

import polygon

def draw_circle(t, circle):
"""Draws a circle.
t: Turtle
circle: Circle
"""
t.pu()
t.goto(circle.center.x, circle.center.y)
t.lt(90)
t.pd()

def draw_rect(t, rect):
"""Draws a rectangle.
t: Turtle
rect: Rectangle
"""
t.pu()
t.goto(rect.corner.x, rect.corner.y)
t.pd()

for length in rect.width, rect.height, rect.width, rect.height:
t.fd(length)
t.rt(90)

if __name__ == '__main__':
bob = turtle.Turtle()

# draw the axes
length = 400
bob.fd(length)
bob.bk(length)
bob.lt(90)
bob.fd(length)
bob.bk(length)

# draw a rectangle
box = Rectangle()
box.width = 100.0
box.height = 200.0
box.corner = Point()
box.corner.x = 50.0
box.corner.y = 50.0

draw_rect(bob, box)

# draw a circle
circle = Circle
circle.center = Point()
circle.center.x = 150.0
circle.center.y = 100.0

draw_circle(bob, circle)

# wait for the user to close the window
turtle.mainloop()```

1. 翻译：@iphyer
2. 校对：@bingjin
3. 参考：@carfly

## 推荐阅读#

##### bert-serving 模型及源代码#
bert-serving 模型及源代码 提供百度网盘下载。

##### 推荐一个非常优惠的QMT开户渠道#

​Python实用宝典 (pythondict.com)