1. 编写一个函数 move_rectangle, 接受一个 Rectangle 对象和两个值,dx,dy。它应当通过添加 dx 到 corner 的 x 坐标和添加 dy 到 corner 的 y 坐标来改换矩形的位置
因为这个练习涉及了很多前面的例子和练习,如果不写出来可能看不懂,所以把需要涉及的内容先写出来。
首先我们定义一个类型叫做类:
class Point(object):
'''Represents a point in 2-D space.'''
print(Point)
<class '__main__.Point'>
然后我们建一个矩形的类:
class Rectangle(object):
'''Represents a rectangle
attributes:width,height,corner.
'''
box=Rectangle()
box.width=100.0 #矩形宽度
box.height=200.0 #矩形高度
box.corner=Point() #corner 是 Point 的一个对象,用来指定左下角的定点
box.corner.x=0
box.corner.y=0
然后然后下面是练习的代码,这个函数相对容易,有三个形参,一个是对象,另外两个值作用在 corner 坐标上,结果如下
def move_rectangle(rect,dx,dy):
rect.corner.x+=dx
rect.corner.y+=dy
move_rectangle(box,10,20)
print_point(box.corner)
(10,20)
对象是可以复制的,我们可以使用 copy 模块对对象进行复制,不过复制分为浅复制 copy 和深复制 deepcopy
import copy
box2=copy.copy(box)
box2 is box
#box2 == box #也会返回 False 因为 == 对于实例来说的默认行为和 is 是相同的
False
box2.corner is box.corner #这表明 copy 复制对象本身但不复制内嵌的 Point 对象,称为浅复制
True
下面是深复制例子
box3=copy.deepcopy(box)# 与浅复制相对,deepcopy 深复制复制对象和内嵌的对象,甚至他们引用的对象以此类推,就是全复制了
box3.corner is box.corner
False
以上所有的举例和练习都是为了让下面的联系好理解
2. 编写 move_rectangle 的一个版本,它会新建并返回一个 Rectangle 对象,而不是直接修改就有的对象
分解这个问题,不直接修改对象移动首先就需要复制矩形,不能用浅复制的原因是虽然矩形被复制了,但是他们共用一个 corner,所以实际上导致原矩形被移动了,所以需要用深复制,不过需要得出一个新对象,我想可不可以用四个参数,第二个参数作为复制第一个参数,不过需要先做一个简要的实验;
def a(rect,rect1):
rect1=copy.copy(rect)
a(box,box1)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-33-550f2a30860b> in <module>
1 def a(rect,rect1):
2 rect1=copy.copy(rect)
----> 3 a(box,box1)
NameError: name 'box1' is not defined
所以使用四个参数的方法有点问题,如果这个参数之前未被定义会报错,所以只能用三个参数,后面想在函数中复制对象,并将此赋值给一个全局对象,后面发现如果使用了 return 就不需要使用全局对象了
import copy
def move_rectangle_copy(rect,dx,dy):
#global rect1
rect1=copy.deepcopy(rect)
rect1.corner.x+=dx
rect1.corner.y+=dy
return rect1
move_rectangle(box,10,20)
print_point(rect1.corner)
结果倒是对了,不过貌似还可以用之前学过的问题识别方法将上面的代码简化,复制对象后面的可以用前面的函数替代:
import copy
def move_rectangle_copy(rect,dx,dy):
rect1=copy.deepcopy(rect)
move_rectangle(rect1,dx,dy)
return rect1
move_rectangle(box,10,20)
print_point(rect1.corner)
这样代码会稍微精简一些。