读《python语言及其应用》做的笔记
目的: 了解python中对象,类,对象,继承,覆盖,self,如何在子类中添加新方法,子类从父类中获得的帮助super(),
属性property,私有特性的命名规范,方法的类型(3种,实例方法,静态方法,类方法),鸭子类型(多态),特殊方法->魔术方法,使用类和模块的选择问题,命名元组的概念。
概念:把对象比作盒子,类则像是制作盒子用的模具。
1,使用class定义类
关键字: class
最简形式
class Person():
pass
调用 someone = Person()
初始化方法添加name参数
class Person():
def __init__(self, name):
self.name
hunter = Person('Elmer Fudd')
print('The mighty hunter:', hunter.name)
The mighty hunter: Elmer Fudd
2,继承
从已有类中衍生出新的类,添加或修改部分功能。
这是代码复用的一个绝佳的例子。
修改得到的新方法会覆盖原有的方法。
定义子类仍用class,不过需要把父类的名字放在子类名字后面的括号里。
(class Yugo(Car))
class Car():
def exclaim(self):
print("I'm a Car")
class Yugo(Car):
pass
3,覆盖方法
子类替代/覆盖父类的方法
class Car():
def exclaim(self):
print("I'm a Car")
class Yugo(Car):
def exclaim(self):
print("I'm a Yugo! Much like a Car, but more Yugo-ish")
give_me_a_car = Car()
give_me_a_Yugo = Yugo()
I'm a Car
I'm a Yugo! Much like a Car, but more Yugo-ish
在子类中可以覆盖任何父类的方法,包括 __init__()。
4,添加新方法
子类可以添加父类中没有的方法。
子类与众不同的特征开始体现。
5,使用super从父类获得帮助
问题: 如果想要调用父类的方法怎么办? ---> super()
下面的例子将定义一个新的类EmailPerson, 用于表示有电子邮件的Person.
class Person():
def __init__(self, name):
self.name = name
class EmailPerson(Person):
def __init__(self, name, email):
super().__init__(name)
self.name = email
在子类中定义__init__()时,父类的会被覆盖。因此,在子类中,父类的初始化方法并不会被调用,我们必须显式的调用它。
1)通过super()方法获取了父类Person的定义
2)子类的__init__()调用了Person.__init__()方法。
3)self.name = email这行新的代码才真正起到了将EmailPerson与Person区分开的作用。
子类可以按照自己的方式处理问题,但如果仍需要借助父类的帮助,使用super()是最佳的选择。
6,self的自辩
调用机制
python在背后做的两件事
1)查找Car对象所属的类(Car)
2)把Car对象作为self参数传给Car类所包含的 exclaim() 方法。
7,使用属性对特性进行访问和设置
编写getter 和 setter方法对私有特性进行读写操作。
python不需要getter 和setter方法,因为python所有特性都是公开的。使用时全凭自觉。
更具python风格的解决方案是使用属性(property)。
8,使用名称重整保护私有特性
python对那些需要刻意隐藏在类内部的特性有自己的命名规范,__开头
self.__name
9,方法的类型
1)实例方法 self
2)类方法 cls @classmethod eg: def kids(cls):
3)静态方法 eg: def commercial():
既不会影响类也不会影响类的对象,它们出现在类的定义中仅仅是为了方便。
@staticmethod
10,鸭子类型
多态
python对实现多态要求的十分宽松,这意味着我们可以对不同对象调用同名的操作,设置不管这些对象的类型是什么
无论对象的种类是什么,只要包含func(),便可以调用它。 func任意名称
这种方式有时候被称作鸭子类型。
11,特殊方法
问题: a = 3 + 8怎么知道如何+ 和 = 的?
python提供的特殊方法,有时候也叫魔术方法。
这些特殊方法的名称以下划线(__)开头和结束。 __eq__
魔术方法!!这个概念。
12,组合
如果想要创建的子类在大多数情况下的行为都和父类相似的话,可以使用继承。 is - a的关系
建立复杂的继承关系确实很吸引人,但有时候使用组合或聚合更加符合现实逻辑。 has - a的关系
13,何时使用类和对象而不是模块
有一些方法可以帮助决定是把代码封装到类里还是模块里。
1)当需要许多具有相似行为但不同状态的实例时,使用对象是最好的选择。
2)类支持继承,但模块不支持。
3)如果想要保证实例的唯一性,使用模块是最好的选择。
不管模块在程序中被引用多少次,始终只有一个实例被加载。
4)如果有一系列包含多个值得变量,并且它们能作为参数传入不同的函数,
那么最好将它们封装到类里面。
5)用最简单的方式解决问题。使用字典,列表和元组往往要比使用模块更加简单、简洁且快速。而实用类则更为复杂。
14,命名元组
命名元组是元组的子类。
既可以通过名称来访问其中的内容,也可以通过位置进行访问。
命名元组并不是python自动支持的类型,使用之前需要加载与其相关的模块。
命名元组是不可变的,但可以替换其中某些域的值并返回一个新的命名元组。
命名元组的好处:
1)它无论看起来还是使用起来都和不可变对象非常相似。
2)与使用对象相比,使用命名元组在时间和空间上效率更高。
3)可以使用点号(.)对特性进行访问,而不需要使用字典风格的方括号。
4)可以把它作为字典的键。