多态、抽象、鸭子、绑定与非绑定、反射与内置方法
一、多态
1、什么是多态?
指的是同一种类型的事物有多种形态。
2、多态的目的:
多态也称为多态性,目的是为了在不知道对象具体类型的情况下,统一对象调用方法的规范。比如:名字。
多态的编写形式之一就是继承
先抽象,再继承
父类:定制一套统一的规范
子类:遵循父类的统一规范
注意:在python中不会强制限制子类必须遵循父类的规范,所以出现了抽象类。
3、多态的三种表现形式:
继承父类 ****
耦合度高,程序的可扩展性低
继承抽象类 ***
耦合度极高,程序的可扩展性极低
鸭子类型: *****
耦合度低,程序的可扩展性高
注意: 在python中,强烈推荐使用鸭子类型。
# # 动物类 # class Animal: # # # 方法 吃 # def eat(self): # pass # # # 方法 叫 # def speak(self): # pass # # 猪类 # class Pig(Animal): # def eat(self): # print('bia唧...') # # def speak(self): # print('哼哼哼...') # # # # 猫类 # class Cat(Animal): # def eat(self): # print('咬ji 咬ji....') # # def speak(self): # print('喵喵喵...') # # # # 狗类 # class Dog(Animal): # def eat(self): # print('舔 ji 舔ji...') # # def speak(self): # print('汪汪汪...') # # # animal1 = Dog() # animal2 = Pig() # animal3 = Cat() # # # 让动物们叫起来 # animal1.speak() # animal2.speak() # animal3.speak()
二、抽象类
1、什么是抽象类?
在python内置的abc模块中,有一个抽象类。
2.作用:
让子类必须遵循父类的编写规范。
3、如何实现:
父类需要继承abc模块中,metaclass=abc.ABCMeta
在父类的方法中,需要装饰上abc.abstracmethod
注意:在python中不推荐使用抽象类。子类必须按照父类的方法编写规范,缺一不可。(只要父类中有几个抽象方法,子类就必须要定义几个)
import abc class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod def eat(self): pass @abc.abstractmethod def speak(self): pass class Cat(Animal): def eat(self): print('bajibaji') def speak(self): print('miaomiao') class Dog(Animal): def eat(self): print('tian') def speak(self): print('wang') def buck(self): print('wang') dog = Dog() cat = Cat()
三、鸭子
1.什么是鸭子类型?
不同的对象,只要长得像鸭子,动作行为像鸭子,那它就是鸭子!
鸭子类型是多态的一种表现形式。
2.为什么要有鸭子类型?
不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范。 所有的类,在定义时都按照统一的规范进行编写。
3、优缺点:
优点:耦合度低,可扩展性高
缺点:容易造成代码冗余
注意: 在python中,强烈推荐使用鸭子类型。
# 猪类 class Pig: def eat(self): print('bia唧...') def speak(self): print('哼哼哼...') # 猫类 class Cat: def eat(self): print('咬ji 咬ji....') def speak(self): print('喵喵喵...') # 狗类 class Dog: def eat(self): print('舔 ji 舔ji...') def speak(self): print('汪汪汪...')
四、绑定与非绑定
绑定 classmethod:
是一个python内置的装饰器,给在类内部方法中装饰,将类内部的方法变为类的绑定方法。
类的绑定方法:
由类来调用,由谁来调用,会将谁(类)当作第一个参数传入。
class DB: __data = 'tank is very handsome!!!' def __init__(self, user, pwd, role): self.user = user self.pwd = pwd self.role = role # @classmethod # def init(cls, user, pwd, role): # cls --》指的是类 # # 在类方法内部调用类产生一个实例 ---》 对象 # return cls(user, pwd, role) # 查看数据方法 @classmethod def check_db(cls, user, pwd, role): # cls --》指的是类 # 在类方法内部调用类产生一个实例 ---》 对象 obj = cls(user, pwd, role) # 1.查看数据前,必须要通过校验 if obj.user == 'tank' and obj.pwd == '123' and obj.role == 'admin': print('检验通过..') print(cls.__data) DB.check_db('tank', '123', 'admin') # db_obj = DB('tank', '123', 'admin') # db_obj.check_db() # __class__: 查看当前对象的类 # print(db_obj.__class__)
非绑定方法staticmethod:
可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。
class Foo: @staticmethod def func(self): print(self) obj = Foo() # obj.func() #此时已经是非绑定,self不再是对象,self变成一个参数,必须传参 #TypeError: func() missing 1 required positional argument: 'self' obj.func(123) #123 此时对象调用非绑定方法 Foo.func(123) #123 此时类调用非绑定方法
五、反射与内置方法
1、内置方法:
isinstance 与issubclass是python内置的模块。
isinstance:判断一个对象是否是另一个类的实例。 结果:True or False
issunclass:判断一个类是否是另一个类的子类。 结果:True or False
isinstance:
class Foo: pass class Bar: pass obj = Foo() print(isinstance(obj, Foo)) #True print(isinstance(obj, Bar)) #False
issunclass:
class Foo: pass class Bar(Foo): pass class Sub: pass # print(issubclass(Bar, Foo)) #True print(issubclass(Sub, Foo)) #False
2、反射
反射:指的是通过 字符串 对 对象的属性 进行操作。
hasattr: 通过 字符串 判断 对象的属性或方法是否存在。 结果:True or False
getattr: 通过 字符串 获取 对象的属性或方法。
setattr: 通过 字符串 设置 对象的属性或方法。
delattr: 通过 字符串 删除 对象的属性或方法。
class Foo: def __init__(self,x, y): self.x = x self.y = y obj = Foo(10,20) #hasattr print(hasattr(obj, 'x')) #True print(hasattr(obj, 'z')) #False #getattr print(getattr(obj, 'x')) #10 print(getattr(obj, 'z')) #AttributeError: 'Foo' object has no attribute 'z' print(getattr(obj, 'z','设置默认返回值可以不报错')) #设置默认返回值可以不报错 #setsttr # 为obj设置一个属性z,值为30 setattr(obj, 'z', 30) print(getattr(obj,'z')) #30 #修改原x的值 setattr(obj, 'x', 30) print(getattr(obj,'x')) #30 #delsttr delattr(obj,'z') print(hasattr(obj, 'z')) #False
反射应用:
class FileControl: def run(self): while True: ## 让用户输入上传或下载功能的命令: uinput = input('请输入上传 upload 或 下载 download 功能:').strip() # 通过用户输入的字符串判断方法是否存在,然后调用相应的方法 if hasattr(self, uinput): func = getattr(self, uinput) func() else: print('输入有误') def upload(self): print('文件正在上传') def download(self): print('文件正在下载') file_obj = FileControl() file_obj.run(