[TOC]
## 第一章 面向对象设计
总体感觉,作者有点罗嗦,他有时开一些可有可无的玩笑,例如,“我们桌上的三个桔子(如果我们还没有吃掉的话)”,括号里的内容并没什么用处。
在Python中,“只读”的概念毫无意义。
多重继承可能是一项棘手的业务,一些编程语言(特别是Java)严格禁止它。
正如我们将在第5章“何时使用面向对象编程”中讨论的,特性关键字在python中对于特定类型的属性具有特殊的含义。
P14:`hollow`是空心的意思,但图中明显是实心箭头。P15也有这个问题。
P16:这里讲的继承和多态是令人迷惑的,标题说“继承提供抽象”,然后貌似讲的是“多态”,貌似继承之所以可以实现,是因为“多态”。
P21:注意异步信息。
P41:叫你的代码如何优雅起来。
## 第三章 当对象是相似的
原书在P60中创建了一个联系人类`Contact`,类中有一个类变量`all_contacts`,类变量在整个实例化的对象中是公用的,注意最后一行是`Contact.all_contacts.append(self)`。
```
class Contact:
all_contacts = []
def __init__(self, name, email):
self.name = name
self.email = email
Contact.all_contacts.append(self)
```
在P62,联系人类`Contact`最后一行变成`self.all_contacts.append(self)`,看起来类变量变成了实例变量,但两段代码运行结果是相同的。至于原因嘛,目前不明。
```
class Contact:
all_contacts = ContactList()
def __init__(self,name,email):
self.name = name
self.email = email
self.all_contacts.append(self)
```
### Basic inheritance
parentClass or supuerClass
```
class Contact:
all_contacts = []
def __init__(self, name, email):
self.name = name
self.email = email
Contact.all_contacts.append(self)
```
```
class Supplier(Contact):
def order(self,order):
print("If this were a real system we would send ""'{}' order to '{}'".format(order,self.name))
# example:
>>> s = Supplier("Sup Plier", "supplier@example.net")
>>> s.order("I need pliers")
```
### Inheriting from built-ins
```
class ContactList(list):
def search(self,name):
matching_contacts = []
for contact in self:
if name in contact.name:
matching_contacts.append(contact)
return matching_contacts
class Contact:
all_contacts = ContactList()
def __init__(self,name,email):
self.name = name
self.email = email
self.all_contacts.append(self)
# example:
>>> c1 = Contact("John A", "johna@example.net")
>>> c2 = Contact("John B", "johnb@example.net")
>>> c3 = Contact("Jenna C", "jennac@example.net")
>>> [c.name for c in Contact.all_contacts.search('John')]
['John A', 'John B']
class LongNameDict(dict):
def longest_key(self):
longest = None
for key in self:
if not longest or len(key) > len(longest):
longest = key
return longest
# example:
>>> longkeys = LongNameDict()
>>> longkeys['hello'] = 1
>>> longkeys['longest yet'] = 5
>>> longkeys['hello2'] = 'world'
>>> longkeys.longest_key()
'longest yet'
```
### Overriding and super
```
class Friend(Contact):
def __init__(self,name,email,num,phone):
super().__init__(name,email,num)
self.phone = phone
```
### Multiple inheritance
The simplest and most useful form of multiple inheritance is called a **mixin**.
```
class MailSender:
def send_mail(self,messeage):
print("Sending mail '{}' to ".format(messeage) + self.email)
class EmailableContact(Contact,MailSender):
pass
# example:
>>> e = EmailableContact("John Smith", "jsmith@example.net")
>>> e.send_mail("Hello, test e-mail here")
Sending mail 'Hello, test e-mail here' to jsmith@example.net
```
```
class AddressHolder:
def __init__(self, street, city, state, code):
self.street = street
self.city = city
self.state = state
self.code = code
# The follow is A very bad method for inheritance ! NOT RECOMMENDED !
class Friend(Contact, AddressHolder):
def __init__(
self, name, email, phone,street, city, state, code):
Contact.__init__(self, name, email)
AddressHolder.__init__(self, street, city, state, code)
self.phone = phone
```
#### Diamond Problem
![](https://box.kancloud.cn/1886a6a98336ec602bd5664dcb8231cf_291x271.png)
```
# The follow are still a bad method and could lead to some insidious bugs! e.g. like depositing into a bank account—twice.
class BaseClass:
num_base_calls = 0
def call_me(self):
print("Calling method on Base Class")
self.num_base_calls += 1
class LeftSubclass(BaseClass):
num_left_calls = 0
def call_me(self):
BaseClass.call_me(self)
print("Calling method on Left Subclass")
self.num_left_calls += 1
class RightSubclass(BaseClass):
num_right_calls = 0
def call_me(self):
BaseClass.call_me(self)
print("Calling method on Right Subclass")
self.num_right_calls += 1
class Subclass(LeftSubclass, RightSubclass):
num_sub_calls = 0
def call_me(self):
LeftSubclass.call_me(self)
RightSubclass.call_me(self)
print("Calling method on Subclass")
self.num_sub_calls += 1
>>> s = Subclass()
>>> s.call_me()
Calling method on Base Class
Calling method on Left Subclass
Calling method on Base Class
Calling method on Right Subclass
Calling method on Subclass
>>> print(
... s.num_sub_calls,
... s.num_left_calls,
... s.num_right_calls,
... s.num_base_calls)
1 1 1 2
```
#### Diamond Problem_Cont
```
# The follow are better methods ! NOT BEST!
class BaseClass:
num_base_calls = 0
def call_me(self):
print("Calling method on Base Class")
self.num_base_calls += 1
class LeftSubclass(BaseClass):
num_left_calls = 0
def call_me(self):
super().call_me()
print("Calling method on Left Subclass")
self.num_left_calls += 1
class RightSubclass(BaseClass):
num_right_calls = 0
def call_me(self):
super().call_me()
print("Calling method on Right Subclass")
self.num_right_calls += 1
class Subclass(LeftSubclass, RightSubclass):
num_sub_calls = 0
def call_me(self):
super().call_me()
print("Calling method on Subclass")
self.num_sub_calls += 1
>>> s = Subclass()
>>> s.call_me()
Calling method on Base Class
Calling method on Right Subclass
Calling method on Left Subclass
Calling method on Subclass
>>> print(s.num_sub_calls, s.num_left_calls, s.num_right_calls,
s.num_base_calls)
1 1 1 1
```
#### Friend multiple inheritance_Cont
```
class Contact:
all_contacts = []
def __init__(self, name='', email='', **kwargs):
super().__init(**kwargs)
self.name = name
self.email = email
self.all_contacts.append(self)
class AddressHolder:
def __init__(self, street='', city='',state='', code='',**kwargs):
super().__init__(**kwargs)
self.street = street
self.city =
```
第六章:
不要使用列表来收集具有单个项目的不同属性。
如果列表含混合的不可排序的项,排序将引发`TypeError`异常。