一、多态
1.什么是多态
多态指的是同一种类型的事物,不同的形态。
例如,猪,狗,猫都是动物,都有叫声这个技能,但是狗是“汪汪汪”,猪是“哼哼哼”,猫是“喵喵喵”。它们之间的叫声不同,也就有了不同的区分
1 # 动物类 2 class Animal: 3 4 # 方法 叫 5 def speak(self): 6 pass 7 # 猪类 8 class Pig(Animal): 9 10 def speak(self): 11 print('哼哼哼...') 12 13 14 # 猫类 15 class Cat(Animal): 16 17 def speak(self): 18 print('喵喵喵...') 19 20 21 # 狗类 22 class Dog(Animal): 23 24 def speak(self): 25 print('汪汪汪...') 26 27 28 animal1 = Dog() 29 animal2 = Pig() 30 animal3 = Cat() 31 32 # 让动物们叫起来 33 animal1.speak() 34 animal2.speak() 35 animal3.speak()
2.多态作用
“多态” 也称之为 “多态性”,目的是为了 在不知道对象具体类型的情况下,统一对象调用方法的规范(比如:名字)。
多态的表现 “形式之一” 就是继承:
- 先抽象,再继承
父类: 定制一套统一的规范。(比如: 方法名统一)
子类: 遵循父类的统一的规范。(比如: 子类遵循父类方法名的统一)
二、抽象类
在python中不会强制限制子类必须要遵循父类的规范,所以出现了抽象类
1.什么是抽象类
在python内置的abc模块中,有一个抽象类
2.抽象类的作用
让子类必须遵循父类的编写规范
3.怎么实现抽象类
- 父类需要继承abc模块中,metaclass=abc.ABCMeta
- 在父类的方法中,需要装饰上 abc.abstractmethod
注意: 在python中不推荐使用抽象类。
注意: 子类必须按照父类的方法编写规范,缺一不可。(只要父类中有几个抽象方法,子类就必须要定义几个)
1 import abc 2 3 class Animal(metaclass= abc.ABCMeta): 4 @abc.abstractmethod 5 def eat(self): 6 pass 7 8 @abc.abstractmethod 9 def speak(self): 10 pass 11 12 13 class Dog(Animal): 14 def eat(self): 15 print('舔') 16 17 def speak(self): 18 print('汪汪汪') 19 20 21 dog_obj = Dog() 22 dog_obj.speak()
三、鸭子类型
1.什么是鸭子类型
不同的对象,只要长得像鸭子,动作行为像鸭子,那它就是鸭子。鸭子类型是多态的一种表现形式。
2.鸭子类型作用
不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范。所有的类,在定义时都按照统一的规范进行编写。降低程序的耦合度。提升了程序的可扩展性
1 # 猪类 2 class Pig: 3 def eat(self): 4 print('bia唧...') 5 6 def speak(self): 7 print('哼哼哼...') 8 9 10 # 猫类 11 class Cat: 12 def eat(self): 13 print('咬ji 咬ji....') 14 15 def speak(self): 16 print('喵喵喵...') 17 18 19 # 狗类 20 class Dog: 21 def eat(self): 22 print('舔 ji 舔ji...') 23 24 def speak(self): 25 print('汪汪汪...') 26 27 28 def animal_speak(animal): 29 animal.speak() 30 31 32 dog = Dog() 33 pig = Pig() 34 cat = Cat() 35 animal_speak(dog) 36 animal_speak(pig) 37 animal_speak(cat)
1 # 自定义统计长度 2 def my_len(obj): 3 return obj.__len__() 4 5 str1 = '123456789' 6 list1 = [1, 2, 3, 4, 5] 7 print(my_len(str1)) 8 print(my_len(list1))
小结:
- 多态的三种表现形式:
- 继承父类 :
- 耦合度高,程序的可扩展性低
- 继承抽象类:
- 耦合度极高,程序的可扩展性极低
- 鸭子类型:
- 耦合度低,程序的可扩展性高
注意: 在python中,强烈推荐使用鸭子类型。
四、classmethod 和 staticmethod
classmethod与staticmethod都是python解释器内置的装饰器
1.classmethod
是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。
1 # classmethod 2 class DB: 3 __data = 'abc' 4 def __init__(self, user, pwd): 5 self.user = user 6 self.pwd = pwd 7 8 9 @classmethod 10 def check(cls, user, pwd): 11 obj = cls(user, pwd) 12 if obj.user == 'aaa' and obj.pwd == '123': 13 print('验证通过...') 14 print(cls.__data) 15 16 DB.check('aaa', '123')
2.staticmethod
是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “非绑定方法”。
1 # staticmethod 2 class Foo: 3 @staticmethod 4 def print_info(self): 5 print(self) 6 7 obj = Foo() 8 9 # 对象调用非绑定方法 10 obj.print_info(123) 11 12 # 类调用非绑定方法 13 Foo.print_info(1234)
小结
- 对象的绑定方法:
- 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。
- 类的绑定方法:
- 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。
- 非绑定方法:
- 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。
五、isinstance 和 issubclass
1.isinstance
判断一个对象是否是另一个类的实例。
- 如果是: True,且这个对象也是该类的父类的一个实例
- 如果不是: False
1 class Foo: 2 pass 3 4 class Sub(Foo): 5 pass 6 7 class Oth: 8 pass 9 10 o_obj = Oth() 11 s_obj = Sub() 12 13 # isinstance 14 print(isinstance(s_obj, Sub)) # True 15 print(isinstance(s_obj, Foo)) # True 16 print(isinstance(s_obj, Oth)) # False
2.issubclass
判断一个类是否是另一个类的子类。
- 如果是: True
- 如果不是: False
1 class Foo: 2 pass 3 4 class Sub(Foo): 5 pass 6 7 class Oth: 8 pass 9 10 o_obj = Oth() 11 s_obj = Sub() 12 13 # issubclass 14 print(issubclass(Sub, Foo)) # True 15 print(issubclass(Sub, Oth)) # False
六、反射
反射指的是通过 “字符串” 对 对象的属性进行操作。
1.hasattr
通过 “字符串” 判断对象的属性或方法是否存在。
2.getattr
通过 “字符串” 获取对象的属性或方法。
3.setattr
通过 “字符串” 设置对象的属性或方法。
4.delattr
通过 “字符串” 删除对象的属性或方法。
1 class Foo: 2 def __init__(self, x, y): 3 self.x = x 4 self.y = y 5 6 obj = Foo(10, 20) 7 print(obj.__dict__) 8 9 # hasattr 10 print(hasattr(obj, 'x')) # True 11 print(hasattr(obj, 'z')) # Flase 12 13 # getattr 14 print(getattr(obj, 'x')) # 10 15 # 若属性不存在,则返回默认值 16 print(getattr(obj, 'z', '不存在返回值')) # 不存在返回值 17 18 # setattr 19 setattr(obj, 'x', 30) 20 print(obj.__dict__) # {'x': 30, 'y': 20} 21 setattr(obj, 'z', '123') 22 print(obj.__dict__) # {'x': 30, 'y': 20, 'z': '123'} 23 24 # delattr 25 delattr(obj, 'z') 26 print(obj.__dict__) # {'x': 30, 'y': 20}
1 # 反射应用 2 class FileControl: 3 4 def run(self): 5 while True: 6 cmd = input('输入要进行功能(upload ---> 上传 download ---> 下载):').strip() 7 if hasattr(self, cmd): 8 func = getattr(self, cmd) 9 func() 10 else: 11 print('输入不合法') 12 13 @staticmethod 14 def upload(): 15 print('上传数据中...') 16 17 @staticmethod 18 def download(): 19 print('下载数据中...') 20 21 22 obj = FileControl() 23 obj.run()