课后练习 第2章 面向对象编程
巩固
R-2.1 给出三个生死攸关的软件应用程序的例子。
1、航天飞机程式错误
2、医疗机器程序错误
3、铁路调度系统出错
原始答案
- 空中交通管制软件
- 计算机集成手术应用程序
- 飞行导航系统
R-2.2 给出一个软件应用程序的例子,其中适应性意味着产品销售和破产的生命周期间的不同。
Windows Phone手机操作系统因为适配软件太少,导致此手机操作系统市场份额日渐减少。
R-2.3 描述文本编辑器GUI的组件和它封装的方法。
class TextEditor:
def __init__(self):
self.text = None
self.textEditor = QTextEdit()
self.menuBar = QMenuBar()
self.toolBar = QToolBar()
def edit(self):
pass
def save(self):
pass
def saveAs(self):
pass
def copy(self):
pass
def paste(self):
pass
R-2.4 编写一个Python类Flower
。该类有str
、int
、float
类型的三种实例变量,分别代表花的名字、花瓣的数量和价格。该类必须包含一个构造函数,该构造函数给每个变量初始化一个合适的值。该类应该包含设置和检索每种类型值的方法。
class Flower:
"""
描述花的类。
"""
def __init__(self, name, number, price):
"""
初始化
:param name: 花的名字
:param number: 花瓣的数量
:param price: 价格
"""
self._name = name
self._number = number
self._price = price
def get_name(self):
return self._name
def set_name(self, name):
self._name = name
def get_number(self):
return self._number
def set_number(self, number):
self._number = number
def get_price(self):
return self._price
def set_price(self, price):
self._price = price
R-2.5 使用1.7节的技术修订CreditCard
类的charge
和make_paymen
t方法确保调用方可以将一个数字作为参数传递。
class CreditCard:
"""
A consumer credit card.消费者信用卡。
"""
def __init__(self, customer, bank, acnt, limit):
"""
Create a new credit card instance.创建一个新的信用卡实例。
The initial balance is zero.初始余额为零。
:param customer: the name of the customer(e.g., 'John Bowman')客户的名字
:param bank: the name of the bank(e.g., 'California Savings')银行名称
:param acnt: the account identifier(e.g., '5391 0375 9387 5309')帐户标识符
:param limit: credit limit(measured in dollars)信用额度
"""
self._customer = customer
self._bank = bank
self._account = acnt
self._limit = limit
self._balance = 0 # 视为已经消费了的,已使用额度。已经花了2000额度。
def get_customer(self):
"""
Return name of the customer.返回客户名称。
:return:
"""
return self._customer
def get_bank(self):
"""
Return the bank's name.返回银行名称。
"""
return self._bank
def get_account(self):
"""
Return the card identifying number(typically stored as a string).返回卡识别号(通常存储为字符串)。
:return:
"""
return self._account
def get_limit(self):
"""
Return current credit limit.返回当前信用额度。
:return:
"""
return self._limit
def get_balance(self):
"""
Return current balance.返回当前余额。
:return:
"""
return self._balance
# 视为信用卡客户消费,balance账单余额
def charge(self, price):
"""
Charge given price to the card, assuming sufficient credit limit.假设有足够的信用额度,按一定价格向信用卡收费。
Return True if charge was processed;False if charge was denied.如果处理了费用,则返回True;如果拒绝了费用,则返回False。
:param price:
:return:
"""
if not isinstance(price, (int, float)):
raise TypeError('Price must be numeric.')
if price + self._balance > self._limit: # f charge would exceed limit.
return False
else:
self._balance += price
return True
# 视为信用卡客户还款,balance账单余额
def make_payment(self, amount):
"""
Process customer payment that reduces balance.处理减少余额的客户付款。
:param amount:
:return:
"""
if not isinstance(amount, (int, float)):
raise TypeError('Amount must be numeric.')
self._balance -= amount
R-2.6 如果CreditCard
类的make_payment
方法接收到的参数是负数,这将影响到账户的余额。修改实现,使得传递的参数值如果为负数,即抛出ValueError
异常。
class CreditCard:
"""
A consumer credit card.消费者信用卡。
"""
def __init__(self, customer, bank, acnt, limit):
"""
Create a new credit card instance.创建一个新的信用卡实例。
The initial balance is zero.初始余额为零。
:param customer: the name of the customer(e.g., 'John Bowman')客户的名字
:param bank: the name of the bank(e.g., 'California Savings')银行名称
:param acnt: the account identifier(e.g., '5391 0375 9387 5309')帐户标识符
:param limit: credit limit(measured in dollars)信用额度
"""
self._customer = customer
self._bank = bank
self._account = acnt
self._limit = limit
self._balance = 0 # 视为已经消费了的,已使用额度。已经花了2000额度。
def get_customer(self):
"""
Return name of the customer.返回客户名称。
:return:
"""
return self._customer
def get_bank(self):
"""
Return the bank's name.返回银行名称。
"""
return self._bank
def get_account(self):
"""
Return the card identifying number(typically stored as a string).返回卡识别号(通常存储为字符串)。
:return:
"""
return self._account
def get_limit(self):
"""
Return current credit limit.返回当前信用额度。
:return:
"""
return self._limit
def get_balance(self):
"""
Return current balance.返回当前余额。
:return:
"""
return self._balance
# 视为信用卡客户消费,balance账单余额
def charge(self, price):
"""
Charge given price to the card, assuming sufficient credit limit.假设有足够的信用额度,按一定价格向信用卡收费。
Return True if charge was processed;False if charge was denied.如果处理了费用,则返回True;如果拒绝了费用,则返回False。
:param price:
:return:
"""
if not isinstance(price, (int, float)):
raise TypeError('Price must be numeric.')
if price + self._balance > self._limit: # f charge would exceed limit.
return False
else:
self._balance += price
return True
# 视为信用卡客户还款,balance账单余额
def make_payment(self, amount):
"""
Process customer payment that reduces balance.处理减少余额的客户付款。
:param amount:
:return:
"""
if not isinstance(amount, (int, float)):
raise TypeError('Amount must be numeric.')
elif amount < 0:
raise ValueError('Amount cannot be negative.')
self._balance -= amount
R-2.7 2.3节的CreditCard
类将一个新账户的余额初始化为零。修改这个类,使构造函数具有第五个参数作为可选参数,它可以初始化一个余额不为零的新账户。而原来的四参数构造函数仍然可以用来生成余额为零的新账户。
class CreditCard:
"""
A consumer credit card.消费者信用卡。
"""
def __init__(self, customer, bank, acnt, limit, balance=0):
"""
Create a new credit card instance.创建一个新的信用卡实例。
The initial balance is zero.初始余额为零。
:param customer: the name of the customer(e.g., 'John Bowman')客户的名字
:param bank: the name of the bank(e.g., 'California Savings')银行名称
:param acnt: the account identifier(e.g., '5391 0375 9387 5309')帐户标识符
:param limit: credit limit(measured in dollars)信用额度
"""
self._customer = customer
self._bank = bank
self._account = acnt
self._limit = limit
self._balance = balance # 视为已经消费了的,已使用额度。已经花了2000额度。
def get_customer(self):
"""
Return name of the customer.返回客户名称。
:return:
"""
return self._customer
def get_bank(self):
"""
Return the bank's name.返回银行名称。
"""
return self._bank
def get_account(self):
"""
Return the card identifying number(typically stored as a string).返回卡识别号(通常存储为字符串)。
:return:
"""
return self._account
def get_limit(self):
"""
Return current credit limit.返回当前信用额度。
:return:
"""
return self._limit
def get_balance(self):
"""
Return current balance.返回当前余额。
:return:
"""
return self._balance
# 视为信用卡客户消费,balance账单余额
def charge(self, price):
"""
Charge given price to the card, assuming sufficient credit limit.假设有足够的信用额度,按一定价格向信用卡收费。
Return True if charge was processed;False if charge was denied.如果处理了费用,则返回True;如果拒绝了费用,则返回False。
:param price:
:return:
"""
if not isinstance(price, (int, float)):
raise TypeError('Price must be numeric.')
if price + self._balance > self._limit: # f charge would exceed limit.
return False
else:
self._balance += price
return True
# 视为信用卡客户还款,balance账单余额
def make_payment(self, amount):
"""
Process customer payment that reduces balance.处理减少余额的客户付款。
:param amount:
:return:
"""
if not isinstance(amount, (int, float)):
raise TypeError('Amount must be numeric.')
elif amount < 0:
raise ValueError('Amount cannot be negative.')
self._balance -= amount
R-2.8 在代码段2-3的CreditCard
类测试中修改第一个for
循环的声明,使三张信用卡的其中一张超过其使用额度。哪张信用卡会出现这种情况?
# 简单,繁琐,不做
R-2.9 实现2.3.3节Vector
类的__sub__
方法,使表达式u - v
返回一个代表两矢量间差异的新矢量实例。
class Vector:
"""
Represent a vector in a multidimensional space.表示多维空间中的向量。
"""
def __init__(self, d):
"""
Create d-dimensional vector of zeros.创建零的d维向量。
:param d:
"""
self._coords = [0] * d
# Python通过特殊方法__iter__为集合提供迭代器的机制。
# 如果一个容器类实现了__len__和__getitem__方法,则它可以自动提供一个默认迭代器。
# 一旦定义了迭代器,就提供了__contains__的默认方法。
def __len__(self):
"""
Return the dimension of the vector.返回向量的维数。
:return:
"""
return len(self._coords)
def __getitem__(self, j):
"""
Return jth coordinate of vector.返回向量的第j个坐标。
:param j:
:return:
"""
return self._coords[j]
def __setitem__(self, j, val):
"""
Set jth coordinate of vector to given value.将向量的第j个坐标设置为给定值。
:param j:
:param val:
:return:
"""
self._coords[j] = val
def __add__(self, other):
"""
Return sum of two vectors.返回两个向量的和。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] + other[j] # 按位加
return result
def __sub__(self, other):
"""
Return difference of two vectors.返回两个向量的差。
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] - other[j]
return result
def __eq__(self, other):
"""
Return True if vector has same coordinates as other.如果向量与其他向量具有相同的坐标,则返回True。
:param other:
:return:
"""
return self._coords == other._coords
def __ne__(self, other):
"""
Return True if vector differs from other.如果向量与其他向量不同,则返回True。
:param other:
:return:
"""
return not self == other # rely on existing __eq__ definition
def __str__(self):
"""
Produce string representation of vector.生成矢量的字符串表示。
:return:
"""
return '<' + str(self._coords[1:-1]) + '>' # adapt list representation调整列表表示
R-2.10 实现2.3.3节Vector
类的__neg__
方法,使表达式-v
返回一个新的矢量实例。新矢量v
的坐标值都是负值。
class Vector:
"""
Represent a vector in a multidimensional space.表示多维空间中的向量。
"""
def __init__(self, d):
"""
Create d-dimensional vector of zeros.创建零的d维向量。
:param d:
"""
self._coords = [0] * d
# Python通过特殊方法__iter__为集合提供迭代器的机制。
# 如果一个容器类实现了__len__和__getitem__方法,则它可以自动提供一个默认迭代器。
# 一旦定义了迭代器,就提供了__contains__的默认方法。
def __len__(self):
"""
Return the dimension of the vector.返回向量的维数。
:return:
"""
return len(self._coords)
def __getitem__(self, j):
"""
Return jth coordinate of vector.返回向量的第j个坐标。
:param j:
:return:
"""
return self._coords[j]
def __setitem__(self, j, val):
"""
Set jth coordinate of vector to given value.将向量的第j个坐标设置为给定值。
:param j:
:param val:
:return:
"""
self._coords[j] = val
def __add__(self, other):
"""
Return sum of two vectors.返回两个向量的和。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] + other[j] # 按位加
return result
def __sub__(self, other):
"""
Return difference of two vectors.返回两个向量的差。
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] - other[j]
return result
def __neg__(self):
"""
Return the negative value of the vector.返回原矢量的负值表示。
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = -self[j]
return result
def __eq__(self, other):
"""
Return True if vector has same coordinates as other.如果向量与其他向量具有相同的坐标,则返回True。
:param other:
:return:
"""
return self._coords == other._coords
def __ne__(self, other):
"""
Return True if vector differs from other.如果向量与其他向量不同,则返回True。
:param other:
:return:
"""
return not self == other # rely on existing __eq__ definition
def __str__(self):
"""
Produce string representation of vector.生成矢量的字符串表示。
:return:
"""
return '<' + str(self._coords[1:-1]) + '>' # adapt list representation调整列表表示
R-2.11 在2.3.3节中,我们注意到Vector
类支持形如v = u + [5, 3, 10, -2, 1]
这样的语法形式,向量和列表的总和返回一个新的向量。然而,语法v = [5, 3, 10, -2,1] + u
确实非法的。解释应该如何修改Vector类的定义使得上述语法能够生成新的向量。
定义一个__radd__函数即可
class Vector:
"""
Represent a vector in a multidimensional space.表示多维空间中的向量。
"""
def __init__(self, d):
"""
Create d-dimensional vector of zeros.创建零的d维向量。
:param d:
"""
self._coords = [0] * d
# Python通过特殊方法__iter__为集合提供迭代器的机制。
# 如果一个容器类实现了__len__和__getitem__方法,则它可以自动提供一个默认迭代器。
# 一旦定义了迭代器,就提供了__contains__的默认方法。
def __len__(self):
"""
Return the dimension of the vector.返回向量的维数。
:return:
"""
return len(self._coords)
def __getitem__(self, j):
"""
Return jth coordinate of vector.返回向量的第j个坐标。
:param j:
:return:
"""
return self._coords[j]
def __setitem__(self, j, val):
"""
Set jth coordinate of vector to given value.将向量的第j个坐标设置为给定值。
:param j:
:param val:
:return:
"""
self._coords[j] = val
def __add__(self, other):
"""
Return sum of two vectors.返回两个向量的和。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] + other[j] # 按位加
return result
def __sub__(self, other):
"""
Return difference of two vectors.返回两个向量的差。
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] - other[j]
return result
def __neg__(self):
"""
Return the negative value of the vector.返回原矢量的负值表示。
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = -self[j]
return result
def __radd__(self, other):
"""
Return the result of adding the right of the vector.返回矢量右加的结果
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = self + other # # rely on definition of __add__
return result
def __eq__(self, other):
"""
Return True if vector has same coordinates as other.如果向量与其他向量具有相同的坐标,则返回True。
:param other:
:return:
"""
return self._coords == other._coords
def __ne__(self, other):
"""
Return True if vector differs from other.如果向量与其他向量不同,则返回True。
:param other:
:return:
"""
return not self == other # rely on existing __eq__ definition
def __str__(self):
"""
Produce string representation of vector.生成矢量的字符串表示。
:return:
"""
return '<' + str(self._coords[1:-1]) + '>' # adapt list representation调整列表表示
R-2.12 实现2.3.3节中的Vector
类的__mul__
方法,使得表达式v * 3
返回一个新的矢量实例,新矢量v
的坐标值都是以前的3倍。
class Vector:
"""
Represent a vector in a multidimensional space.表示多维空间中的向量。
"""
def __init__(self, d):
"""
Create d-dimensional vector of zeros.创建零的d维向量。
:param d:
"""
self._coords = [0] * d
# Python通过特殊方法__iter__为集合提供迭代器的机制。
# 如果一个容器类实现了__len__和__getitem__方法,则它可以自动提供一个默认迭代器。
# 一旦定义了迭代器,就提供了__contains__的默认方法。
def __len__(self):
"""
Return the dimension of the vector.返回向量的维数。
:return:
"""
return len(self._coords)
def __getitem__(self, j):
"""
Return jth coordinate of vector.返回向量的第j个坐标。
:param j:
:return:
"""
return self._coords[j]
def __setitem__(self, j, val):
"""
Set jth coordinate of vector to given value.将向量的第j个坐标设置为给定值。
:param j:
:param val:
:return:
"""
self._coords[j] = val
def __add__(self, other):
"""
Return sum of two vectors.返回两个向量的和。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] + other[j] # 按位加
return result
def __sub__(self, other):
"""
Return difference of two vectors.返回两个向量的差。
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] - other[j]
return result
def __neg__(self):
"""
Return the negative value of the vector.返回原矢量的负值表示。
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = -self[j]
return result
def __radd__(self, other):
"""
Return the result of adding the right of the vector.返回矢量右加的结果
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = self + other # # rely on definition of __add__
return result
def __mul__(self, n):
"""
Return a vector whose value is n times the original vector.返回值是原来矢量n倍的矢量。
:param other:
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = n * self[j]
return result
def __eq__(self, other):
"""
Return True if vector has same coordinates as other.如果向量与其他向量具有相同的坐标,则返回True。
:param other:
:return:
"""
return self._coords == other._coords
def __ne__(self, other):
"""
Return True if vector differs from other.如果向量与其他向量不同,则返回True。
:param other:
:return:
"""
return not self == other # rely on existing __eq__ definition
def __str__(self):
"""
Produce string representation of vector.生成矢量的字符串表示。
:return:
"""
return '<' + str(self._coords[1:-1]) + '>' # adapt list representation调整列表表示
R-2.13 练习R-2.12要求对2.3.3节中的Vector
类实现__mul__
方法,以提供对语法v*3
的支持。使实现__rmul__
方法,提供对语法3*v
的支持。
class Vector:
"""
Represent a vector in a multidimensional space.表示多维空间中的向量。
"""
def __init__(self, d):
"""
Create d-dimensional vector of zeros.创建零的d维向量。
:param d:
"""
self._coords = [0] * d
# Python通过特殊方法__iter__为集合提供迭代器的机制。
# 如果一个容器类实现了__len__和__getitem__方法,则它可以自动提供一个默认迭代器。
# 一旦定义了迭代器,就提供了__contains__的默认方法。
def __len__(self):
"""
Return the dimension of the vector.返回向量的维数。
:return:
"""
return len(self._coords)
def __getitem__(self, j):
"""
Return jth coordinate of vector.返回向量的第j个坐标。
:param j:
:return:
"""
return self._coords[j]
def __setitem__(self, j, val):
"""
Set jth coordinate of vector to given value.将向量的第j个坐标设置为给定值。
:param j:
:param val:
:return:
"""
self._coords[j] = val
def __add__(self, other):
"""
Return sum of two vectors.返回两个向量的和。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] + other[j] # 按位加
return result
def __sub__(self, other):
"""
Return difference of two vectors.返回两个向量的差。
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] - other[j]
return result
def __neg__(self):
"""
Return the negative value of the vector.返回原矢量的负值表示。
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = -self[j]
return result
def __radd__(self, other):
"""
Return the result of adding the right of the vector.返回矢量右加的结果
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = self + other # # rely on definition of __add__
return result
def __mul__(self, n):
"""
Return a vector whose value is n times the original vector.返回值是原来矢量n倍的矢量。
:param other:
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] * n
return result
def __rmul__(self, n):
"""
Return a vector whose value is n times the original vector.返回值是原来矢量n倍的矢量。
:param other:
:return:
"""
return self * n # rely on definition of __mul__
def __eq__(self, other):
"""
Return True if vector has same coordinates as other.如果向量与其他向量具有相同的坐标,则返回True。
:param other:
:return:
"""
return self._coords == other._coords
def __ne__(self, other):
"""
Return True if vector differs from other.如果向量与其他向量不同,则返回True。
:param other:
:return:
"""
return not self == other # rely on existing __eq__ definition
def __str__(self):
"""
Produce string representation of vector.生成矢量的字符串表示。
:return:
"""
return '<' + str(self._coords[1:-1]) + '>' # adapt list representation调整列表表示
R-2.14 实现2.3.3节Vector
类的__mul__
方法,使表达式u * v
返回一个标量代表向量点运算的结果,即
∑
i
=
1
d
u
i
∗
v
i
\sum_{i=1}^{d}u_{i}*v_{i}
∑i=1dui∗vi。
from collections.abc import Sequence
class Vector:
"""
Represent a vector in a multidimensional space.表示多维空间中的向量。
"""
def __init__(self, d):
"""
Create d-dimensional vector of zeros.创建零的d维向量。
:param d:
"""
if isinstance(d, (int, float)):
self._coords = [0] * d
elif isinstance(d, Sequence):
self._coords = list(d)
# Python通过特殊方法__iter__为集合提供迭代器的机制。
# 如果一个容器类实现了__len__和__getitem__方法,则它可以自动提供一个默认迭代器。
# 一旦定义了迭代器,就提供了__contains__的默认方法。
def __len__(self):
"""
Return the dimension of the vector.返回向量的维数。
:return:
"""
return len(self._coords)
def __getitem__(self, j):
"""
Return jth coordinate of vector.返回向量的第j个坐标。
:param j:
:return:
"""
return self._coords[j]
def __setitem__(self, j, val):
"""
Set jth coordinate of vector to given value.将向量的第j个坐标设置为给定值。
:param j:
:param val:
:return:
"""
self._coords[j] = val
def __add__(self, other):
"""
Return sum of two vectors.返回两个向量的和。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] + other[j] # 按位加
return result
def __sub__(self, other):
"""
Return difference of two vectors.返回两个向量的差。
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] - other[j]
return result
def __neg__(self):
"""
Return the negative value of the vector.返回原矢量的负值表示。
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = -self[j]
return result
def __radd__(self, other):
"""
Return the result of adding the right of the vector.返回矢量右加的结果
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = self + other # # rely on definition of __add__
return result
def __mul__(self, n):
"""
Return a vector whose value is n times the original vector.返回值是原来矢量n倍的矢量。
:param other:
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] * n
return result
def __mul__(self, other):
"""
Return products of two vectors.返回两个向量的积。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] * other[j] # 按位加
return result
def __rmul__(self, n):
"""
Return a vector whose value is n times the original vector.返回值是原来矢量n倍的矢量。
:param other:
:return:
"""
return self * n # rely on definition of __mul__
def __eq__(self, other):
"""
Return True if vector has same coordinates as other.如果向量与其他向量具有相同的坐标,则返回True。
:param other:
:return:
"""
return self._coords == other._coords
def __ne__(self, other):
"""
Return True if vector differs from other.如果向量与其他向量不同,则返回True。
:param other:
:return:
"""
return not self == other # rely on existing __eq__ definition
def __str__(self):
"""
Produce string representation of vector.生成矢量的字符串表示。
:return:
"""
return '<' + str(self._coords[1:-1]) + '>' # adapt list representation调整列表表示
if __name__ == '__main__':
vector = Vector([2, 3, 3])
R-2.15 2.3.3节的Vector
类提供接受一个整数d的构造函数,并产生一个d
维向量,它的所有坐标等于0。另一种创建矢量的便捷方式使给构造函数传递一个参数,一些迭代类型可以代表一系列的数字,创建一个向量,它的维度等于序列的长度,坐标值等于序列的值。例如,Vector([7, 4, 5])
会产生一个三维向量,坐标值为<7, 4, 5>
。修改构造函数,使它可以接受任何形式的参数。也就是说,如果一个整数被传递,它就产生了一个所有坐标值为零的向量。但是如果提供了一个序列,它就产生了一个坐标值等于序列值的向量。
from collections.abc import Sequence
class Vector:
"""
Represent a vector in a multidimensional space.表示多维空间中的向量。
"""
def __init__(self, d):
"""
Create d-dimensional vector of zeros.创建零的d维向量。
:param d:
"""
if isinstance(d, (int, float)):
self._coords = [0] * d
elif isinstance(d, Sequence):
self._coords = list(d)
# Python通过特殊方法__iter__为集合提供迭代器的机制。
# 如果一个容器类实现了__len__和__getitem__方法,则它可以自动提供一个默认迭代器。
# 一旦定义了迭代器,就提供了__contains__的默认方法。
def __len__(self):
"""
Return the dimension of the vector.返回向量的维数。
:return:
"""
return len(self._coords)
def __getitem__(self, j):
"""
Return jth coordinate of vector.返回向量的第j个坐标。
:param j:
:return:
"""
return self._coords[j]
def __setitem__(self, j, val):
"""
Set jth coordinate of vector to given value.将向量的第j个坐标设置为给定值。
:param j:
:param val:
:return:
"""
self._coords[j] = val
def __add__(self, other):
"""
Return sum of two vectors.返回两个向量的和。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] + other[j] # 按位加
return result
def __sub__(self, other):
"""
Return difference of two vectors.返回两个向量的差。
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] - other[j]
return result
def __neg__(self):
"""
Return the negative value of the vector.返回原矢量的负值表示。
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = -self[j]
return result
def __radd__(self, other):
"""
Return the result of adding the right of the vector.返回矢量右加的结果
:param other:
:return:
"""
if len(self) != len(other):
raise ValueError('dimensions must be agree')
result = self + other # # rely on definition of __add__
return result
def __mul__(self, n):
"""
Return a vector whose value is n times the original vector.返回值是原来矢量n倍的矢量。
:param other:
:return:
"""
result = Vector(len(self))
for j in range(len(self)):
result[j] = self[j] * n
return result
def __mul__(self, other):
"""
Return products of two vectors.返回两个向量的积。
:param other:
:return:
"""
if len(self) != len(other): # relies on __len__ method
raise ValueError('dimensions must agree')
result = Vector(len(self)) # start with vector of zeros
for j in range(len(self)):
result[j] = self[j] * other[j] # 按位加
return result
def __rmul__(self, n):
"""
Return a vector whose value is n times the original vector.返回值是原来矢量n倍的矢量。
:param other:
:return:
"""
return self * n # rely on definition of __mul__
def __eq__(self, other):
"""
Return True if vector has same coordinates as other.如果向量与其他向量具有相同的坐标,则返回True。
:param other:
:return:
"""
return self._coords == other._coords
def __ne__(self, other):
"""
Return True if vector differs from other.如果向量与其他向量不同,则返回True。
:param other:
:return:
"""
return not self == other # rely on existing __eq__ definition
def __str__(self):
"""
Produce string representation of vector.生成矢量的字符串表示。
:return:
"""
return '<' + str(self._coords[1:-1]) + '>' # adapt list representation调整列表表示
if __name__ == '__main__':
vector = Vector([2, 3, 3])
R-2.16 2.3.5节的Range
类按照如下公式max(0, (stop -start + step -1) // step)
去计算范围内元素的数量。即使假设一个正的step
大小,也并不能很明显地看出为什么这个公式提供了正确的计算。可以用你自己的方式证明这个公式。
如果我们要一次增加一个停止值,那么新值会在什么时候出现在范围内?
待解决
R-2.17 从下面类的集合中画一个类的继承图:
- Goat类扩展了object类,增加了实例变量_tail以及方法milk()和jump()。
- Pig类扩展了object类,增加了实例变量_nose以及方法eat(food)和wallow()。
- Horse类扩展了object类,增加了实例变量_height和_color以及方法run()和jump()。
- Racer类扩展了Horse类,增加了方法race()。
- Equestrain类扩展了Horse类,增加了实例变量_weight以及方法trot()和is_trained()。**
太繁琐,不做
R-2.18 给出一个来自Python代码的简短片段,使用2.4.2节的Progression
类,找到那个以2开始且以2作为前两个值的斐波那契数列的第8个值。
class Progression:
"""
Iterator producing a generic progression.产生一般级数的迭代器。
Default iterator produces the whole numbers 0,1,2...默认迭代器生成整数0,1,2。。。
"""
def __init__(self, start=0):
"""
Initialize current to the first value of the progression.将当前值初始化为级数的第一个值。
"""
self._current = start
def _advance(self):
"""
Update self._current to a new value.更新self._current为新值。
This should be overridden by a subclass to customize progression.这应该由一个子类重写以自定义进程。
By convention, if current is set to None, this designates the end of a finite progression.
按照惯例,如果current设置为None,这将指定有限进程的结束。
:return:
"""
self._current += 1
def __next__(self):
"""
Return the next element, or else raise StopIteration error.返回下一个元素,否则将引发StopIteration错误。
:return:
"""
if self._current is None: # our convention to end a progression.我们结束进程的公约。
raise StopIteration
else:
answer = self._current # record current value to return记录当前值以返回
self._advance() # advance to prepare for next time提前准备下一次
return answer # return the answer返回答案
def __iter__(self):
"""
By convention, an iterator must return itself as an iterator.按照约定,迭代器必须将自身作为迭代器返回。
:return:
"""
return self
def print_progression(self, n):
"""
Print next n value of the progression.打印进程的下一个n值。
:param n:
:return:
"""
print(' '.join(str(next(self)) for j in range(n)))
class FibonacciProgression(Progression):
"""
Iterator producing a generalized Fibonacci progression.产生广义Fibonacci级数的迭代器。
"""
def __init__(self, first=0, second=1):
"""
Create a new fibonacci progression.创建一个新的斐波那契级数。
:param first: # the first term of the progression(default 0)级数的第一个项(默认为0)
:param second: # the second term of the progression(default 1)级数的第二项(默认值1)
"""
super().__init__(first) # start progression at first先开始进步
self._prev = second - first # fictitious value preceding the first第一个之前的虚拟值
def _advance(self):
"""
Update current value by taking sum of previous two.取前两个值之和更新当前值。
:return:
"""
self._prev, self._current = self._current, self._prev + self._current
if __name__ == '__main__':
FibonacciProgression(2, 2).print_progression(8)
# out will be 2 2 4 6 10 16 26 42
42
R-2.19 利用2.4.2节的ArithmeticProgression
类,以0开始,增量为128,在到达整数
2
63
2^{63}
263或者更大的数时,我们需要执行多少次的调用?
class Progression:
"""
Iterator producing a generic progression.产生一般级数的迭代器。
Default iterator produces the whole numbers 0,1,2...默认迭代器生成整数0,1,2。。。
"""
def __init__(self, start=0):
"""
Initialize current to the first value of the progression.将当前值初始化为级数的第一个值。
"""
self._current = start
def _advance(self):
"""
Update self._current to a new value.更新self._current为新值。
This should be overridden by a subclass to customize progression.这应该由一个子类重写以自定义进程。
By convention, if current is set to None, this designates the end of a finite progression.
按照惯例,如果current设置为None,这将指定有限进程的结束。
:return:
"""
self._current += 1
def __next__(self):
"""
Return the next element, or else raise StopIteration error.返回下一个元素,否则将引发StopIteration错误。
:return:
"""
if self._current is None: # our convention to end a progression.我们结束进程的公约。
raise StopIteration
else:
answer = self._current # record current value to return记录当前值以返回
self._advance() # advance to prepare for next time提前准备下一次
return answer # return the answer返回答案
def __iter__(self):
"""
By convention, an iterator must return itself as an iterator.按照约定,迭代器必须将自身作为迭代器返回。
:return:
"""
return self
def print_progression(self, n):
"""
Print next n value of the progression.打印进程的下一个n值。
:param n:
:return:
"""
print(' '.join(str(next(self)) for j in range(n)))
class ArithmeticProgression(Progression): # inherit from Progression
"""
Iterator producing an arithmetic progression.产生算术级数的迭代器。
"""
def __init__(self, increment=1, start=0):
"""
Create a new arithmetic progression.创建一个新的算术级数。
:param increment: the fixed constant to add to each term(default 1)要添加到每个项的固定常数(默认值1)
:param start: the first term of the progression (default 0)级数的第一个项(默认为0)
"""
super().__init__(start) # initialize base class
self._increment = increment
def _advance(self): # override inherited version重写继承的版本
"""
Update current value by adding the fixed increment.通过添加固定增量来更新当前值。
:return:
"""
self._current += self._increment
if __name__ == '__main__':
ArithmeticProgression(128, 0).print_progression(2**56)
2 56 2^{56} 256次调用
R-2.20 拥有一颗非常深的继承树
会有哪些潜在的效率劣势?也就是说,有一个很大的类的集合,A、B、C……,其中B继承自A、C继承自B、D继承自C……
想一想当创建类Z的新实例以及调用类Z的方法时会发生什么。
有两种直接的效率低下:
- (1)构造函数的链接意味着,每次创建深层类Z的实例时,方法调用的潜在集合就会很长
- (2)用于确定要使用某种方法的哪个版本的动态调度算法最终可能会在找到合适的类之前先浏览大量类。
R-2.21 拥有一颗非常浅的继承树
会有哪些潜在的效率劣势?也就是说,有一个很大的类的集合,A、B、C……所有的这些类扩展来自一个单一的类Z。
考虑一下代码重用。
每当大量类都从单个类扩展时,很可能您会错过不同类中类似方法的潜在代码重用。 在这种情况下,有可能将方法分解为通用类,这可以通过消除重复的代码来节省程序员的时间和维护时间。
R-2.22 collections.Sequence
抽象基类不提供对两个序列的比较支持,从代码段2-14中修改Sequence类,使其定义包含__eq__
方法,使两个序列中的元素相等时,表达式seq1 == seq2
返回True。
from abc import ABCMeta, abstractmethod # need these definitions
class Sequence(metaclass=ABCMeta):
"""
Our own version of collections.Sequence abstract base class.
"""
@abstractmethod
def __len__(self):
"""
Return the length of the sequence.
:return:
"""
@abstractmethod
def __getitem__(self, j):
"""
Return the element at index j of the sequence.
:param item:
:return:
"""
def __contains__(self, val):
"""
Return True if val found in the sequence;False otherwise.
:param val:
:return:
"""
for j in range(len(self)):
if self[j] == val:
return True # found match
raise False
def index(self, val):
"""
Return leftmost index at which val is found(or raise ValueError).
:param val:
:return:
"""
for j in range(len(self)):
if self[j] == val:
return j # leftmost match
raise ValueError("value not in sequence") # never found a match
def count(self, val):
"""
Return the number of elements equal to given value.
:param val:
:return:
"""
k = 0
for j in range(len(self)):
if self[j] == val: # found a match
k += 1
return k
def __eq__(self, other):
if len(self) != other:
raise ValueError('dimension must agree')
else:
for i in range(len(self)):
if self[i] != other[i]:
return False
return True
**R-2.23 在之前的问题中右类似的问题,使用方法__it__
参数化Sequence
类,使其支持字典比较seq1 < seq2.
**
from abc import ABCMeta, abstractmethod # need these definitions
class Sequence(metaclass=ABCMeta):
"""
Our own version of collections.Sequence abstract base class.
"""
@abstractmethod
def __len__(self):
"""
Return the length of the sequence.
:return:
"""
@abstractmethod
def __getitem__(self, j):
"""
Return the element at index j of the sequence.
:param item:
:return:
"""
def __contains__(self, val):
"""
Return True if val found in the sequence;False otherwise.
:param val:
:return:
"""
for j in range(len(self)):
if self[j] == val:
return True # found match
raise False
def index(self, val):
"""
Return leftmost index at which val is found(or raise ValueError).
:param val:
:return:
"""
for j in range(len(self)):
if self[j] == val:
return j # leftmost match
raise ValueError("value not in sequence") # never found a match
def count(self, val):
"""
Return the number of elements equal to given value.
:param val:
:return:
"""
k = 0
for j in range(len(self)):
if self[j] == val: # found a match
k += 1
return k
def __eq__(self, other):
if len(self) != other:
raise ValueError('dimension must agree')
else:
for i in range(len(self)):
if self[i] != other[i]:
return False
return True
def lt(self, other):
for k in range(min(len(self), len(other))):
if self[k] < other[k]:
return True
elif self[k] > other[k]:
return False
# otherwise elements are equal thus far...
# if reached the end, require that self be a strict prefix of other
return len(self) < len(other)