多态
1.什么是多态?
多态指的是同一种类型的事物,不同的形态。
2.多态的目的:
“多态” 也称之为 “多态性”,目的是为了 在不知道对象具体类型的情况下,统一对象调用方法的规范(比如:名字)。
多态的表现 “形式之一” 就是继承:
- 先抽象,再继承
父类: 定制一套统一的规范。(比如: 方法名统一)
子类: 遵循父类的统一的规范。(比如: 子类遵循父类方法名的统一)
注意: 在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.abstractmethod
注意: 在python中不推荐使用抽象类。
注意: 子类必须按照父类的方法编写规范,缺一不可。(只要父类中有几个抽象方法,子类就必须要定义几个)
import abc # 父类 class Animal(metaclass=abc.ABCMeta): # 方法 吃 @abc.abstractmethod def eat(self): pass # 方法 叫 @abc.abstractmethod def speak(self): pass # 猪类 class Pig(Animal): def run(self): pass def eat(self): print('bia唧...') def speak(self): print('哼哼哼...') print(Pig.__dict__) print(Animal.__dict__) pig_obj = Pig()
鸭子类型
1.什么是鸭子类型?
不同的对象,只要长得像鸭子,动作行为像鸭子,那它就是鸭子!
鸭子类型是多态的一种表现形式。
2.为什么要有鸭子类型?
不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范。
所有的类,在定义时都按照统一的规范进行编写。
- 多态的三种表现形式:
- 继承父类 ****
- 耦合度高,程序的可扩展性低
- 继承抽象类 ***
- 耦合度极高,程序的可扩展性极低
- 鸭子类型: *****
- 耦合度低,程序的可扩展性高
注意: 在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("汪汪汪...")
多态之炫技
# 猪类 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("汪汪汪...") dog = Dog() pig=Pig() cat=Cat() # 多态之炫技 def SPEAK(animal): animal.speak() SPEAK(dog) SPEAK(cat) SPEAK(pig) str1 = 'tank is very handsome!!!' list1 = ['tank', 'is', 'very', 'handsome!!!'] # 自定义统计长度函数 def LEN(obj): return obj.__len__() print(LEN(str1)) # 24 print(LEN(list1)) # 4
classmethod 与 staticmethod
classmethod与staticmethod都是python解释器内置的装饰器。 *******
classmethod:
是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。
staticmethod:
翻译: 静态方法
是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “非绑定方法”。
- 对象的绑定方法:
- 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。
- 类的绑定方法:
- 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。
- 非绑定方法:
- 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。
# classmethod_Demo: 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) return cls.__data DB.check_db('tank', '123', 'admin')
obj=DB('tank','123','admin')
obj.check_db('tank','123','admin') # 也可以,第一个传入参数依然是类,但没什么意义
# staticmethod_Demo: class Foo: @staticmethod def func(res): print(res) obj = Foo() #对象调用非绑定方法 obj.func(123) #类调用非绑定方法 Foo.func(1234)
uuid 用于产生随机字符串的模块
import uuid # 用于产生随机字符串的模块 # 由时间戳以及某种算法组合而成,会产生一串世界上独一无二字符串。 print(uuid.uuid4()) # f93f9c3b-eef4-4001-922e-2124b48ca7ab
内置模块:isinstance与issubclass
isinstance与issubclass是python的内置模块: *******
- isinstance: 判断一个对象是否是另一个类的实例。
- 如果是: True
- 如果不是: False
- issubclass: 判断一个类是否是另一个类的子类。
- 如果是: True
- 如果不是: False
# isinstance: class Foo: pass class Boo: pass foo_obj = Foo() boo_obj = Boo() print(isinstance(foo_obj, Foo)) # True print(isinstance(boo_obj, Foo)) # False # issubclass class Father: pass class Sub(Father): pass class Foo: pass print(issubclass(Sub, Father)) # True print(issubclass(Foo, Father)) # False
反射
反射: *******
反射指的是通过 “字符串” 对 对象的属性进行操作。
- hasattr: 通过 字符串 判断对象的属性或方法是否存在,存在返回True, 否则返回False。
hasattr(对象, '对象的属性或方法字符串')
- getattr: 通过 字符串 获取对象的属性或方法是否存在,存在返回获取属性或方法, 否则返回报错。
getattr(对象, '对象的属性或方法字符串', '默认值')
- setattr: 通过 字符串 设置(添加/修改)对象的属性或方法。
setattr(对象, '对象的属性或方法字符串', '属性的值')
- delattr: 通过 字符串 删除 对象的属性或方法,若属性不存在,则报错。
delattr(对象, '对象的属性或方法字符串')
# 注意: 反射的四个方法是python内置的。
class Foo: def __init__(self, x, y): self.x = x self.y = y foo_obj = Foo(10, 20) # hasattr # 通过字符串x 判断对象中是否有 x属性 print(hasattr(foo_obj, 'x')) # True print(hasattr(foo_obj, 'y')) # True print(hasattr(foo_obj, 'z')) # False # getattr res = getattr(foo_obj, 'x') print(res) # 10 # 若属性不存在,则返回默认值 res = getattr(foo_obj, 'z', '默认值') print(res) # 默认值 # setattr setattr(foo_obj,'x',40) print(getattr(foo_obj,'x')) # 40 # 为foo_obj设置一个属性z,值为30 setattr(foo_obj, 'z', 30) print(hasattr(foo_obj, 'z')) # True # delattr delattr(foo_obj, 'x') print(hasattr(foo_obj, 'x')) # False
# 反射应用: class FileControl: def run(self): while True: # 让用户输入上传或下载功能的命令: user_input = input('请输入 上传(upload) 或 下载(download) 功能:').strip() # 通过用户输入的字符串判断方法是否存在,然后调用相应的方法 if hasattr(self, user_input): func = getattr(self, user_input) func() else: print('输入有误!') def upload(self): print('文件正在上传...') def download(self): print('文件正在下载...') file_control_obj = FileControl() file_control_obj.run()
以下为验证,反射中将输入输入字符创转化为方法
# 代码同上,用来测试反射里面类型变化 class choose: def run(self): while True: cmd = input('请输入命令:').strip() if hasattr(self,cmd): print(getattr(self,cmd)) # 把字符串转化为方法 # <bound method choose.load of <__main__.choose object at 0x00000000022A5F28>> print(type(getattr(self,cmd))) # <class 'method'> getattr(self,cmd)() # 运行方法 else: print('输入有误') def load(self): print('load') def down(self): print('down') obj = choose() print(type(obj.load)) # <class 'method'> obj.run()