🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[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`异常。