多态
1.什么是多态?
多态指的是同一种类型的事物,不同的形态。
2.多态的目的:
“多态” 也称之为 “多态性”,目的是为了 在不知道对象具体类型的情况下,统一对象调用方法的规范(比如:名字)。
多态的表现 “形式之一” 就是继承:
- 先抽象,再继承
父类: 定制一套统一的规范。(比如: 方法名统一)
子类: 遵循父类的统一的规范。(比如: 子类遵循父类方法名的统一)
注意: 在python中不会强制限制 子类 必须要遵循 父类 的规范,所以出现了抽象类。
#动物类
classAnimal:#方法 吃
defeat(self):pass
#方法 叫
defspeak(self):pass
#猪类
classPig(Animal):defeat(self):print('bia唧...')defspeak(self):print('哼哼哼...')#猫类
classCat(Animal):defeat(self):print('咬ji 咬ji....')defspeak(self):print('喵喵喵...')#狗类
classDog(Animal):defeat(self):print('舔 ji 舔ji...')defspeak(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中不推荐使用抽象类。
注意: 子类必须按照父类的方法编写规范,缺一不可。(只要父类中有几个抽象方法,子类就必须要定义几个)
importabc#父类
class Animal(metaclass=abc.ABCMeta):#方法 吃
@abc.abstractmethoddefeat(self):pass
#方法 叫
@abc.abstractmethoddefspeak(self):pass
#猪类
classPig(Animal):defrun(self):pass
defeat(self):print('bia唧...')defspeak(self):print('哼哼哼...')print(Pig.__dict__)print(Animal.__dict__)
pig_obj= Pig()
鸭子类型
1.什么是鸭子类型?
不同的对象,只要长得像鸭子,动作行为像鸭子,那它就是鸭子!
鸭子类型是多态的一种表现形式。
2.为什么要有鸭子类型?
不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范。
所有的类,在定义时都按照统一的规范进行编写。
- 多态的三种表现形式:
- 继承父类 ****
- 耦合度高,程序的可扩展性低
- 继承抽象类 ***
- 耦合度极高,程序的可扩展性极低
- 鸭子类型: *****
- 耦合度低,程序的可扩展性高
注意: 在python中,强烈推荐使用鸭子类型。
#猪类
classPig:defeat(self):print('bia唧...')defspeak(self):print('哼哼哼...')#猫类
classCat:defeat(self):print('咬ji 咬ji...')defspeak(self):print('喵喵喵...')#狗类
classDog:defeat(self):print('舔 ji 舔ji...')defspeak(self):print("汪汪汪...")
多态之炫技
#猪类
classPig:defeat(self):print('bia唧...')defspeak(self):print('哼哼哼...')#猫类
classCat:defeat(self):print('咬ji 咬ji...')defspeak(self):print('喵喵喵...')#狗类
classDog:defeat(self):print('舔 ji 舔ji...')defspeak(self):print("汪汪汪...")
dog=Dog()
pig=Pig()
cat=Cat()#多态之炫技
defSPEAK(animal):
animal.speak()
SPEAK(dog)
SPEAK(cat)
SPEAK(pig)
str1= 'tank is very handsome!!!'list1= ['tank', 'is', 'very', 'handsome!!!']#自定义统计长度函数
defLEN(obj):return obj.__len__()print(LEN(str1)) #24
print(LEN(list1)) #4
classmethod 与 staticmethod
classmethod与staticmethod都是python解释器内置的装饰器。 *******
classmethod:
是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。
staticmethod:
翻译: 静态方法
是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “非绑定方法”。
- 对象的绑定方法:
- 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。
- 类的绑定方法:
- 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。
- 非绑定方法:
- 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。
#classmethod_Demo:
classDB:__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)
#查看数据方法
@classmethoddef 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.__dataDB.check_db('tank', '123', 'admin')
obj=DB('tank','123','admin')
obj.check_db('tank','123','admin') # 也可以,第一个传入参数依然是类,但没什么意义
#staticmethod_Demo:
classFoo:
@staticmethoddeffunc(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:
classFoo:pass
classBoo:passfoo_obj=Foo()
boo_obj=Boo()print(isinstance(foo_obj, Foo)) #True
print(isinstance(boo_obj, Foo)) #False
#issubclass
classFather:pass
classSub(Father):pass
classFoo:pass
print(issubclass(Sub, Father)) #True
print(issubclass(Foo, Father)) #False
反射
反射: *******
反射指的是通过 “字符串” 对 对象的属性进行操作。
- hasattr: 通过 字符串 判断对象的属性或方法是否存在,存在返回True, 否则返回False。
hasattr(对象, '对象的属性或方法字符串')
- getattr: 通过 字符串 获取对象的属性或方法是否存在,存在返回获取属性或方法, 否则返回报错。
getattr(对象, '对象的属性或方法字符串', '默认值')
- setattr: 通过 字符串 设置(添加/修改)对象的属性或方法。
setattr(对象, '对象的属性或方法字符串', '属性的值')
- delattr: 通过 字符串 删除 对象的属性或方法,若属性不存在,则报错。
delattr(对象, '对象的属性或方法字符串')
# 注意: 反射的四个方法是python内置的。
classFoo: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
#反射应用:
classFileControl:defrun(self):whileTrue:#让用户输入上传或下载功能的命令:
user_input = input('请输入 上传(upload) 或 下载(download) 功能:').strip()#通过用户输入的字符串判断方法是否存在,然后调用相应的方法
ifhasattr(self, user_input):
func=getattr(self, user_input)
func()else:print('输入有误!')defupload(self):print('文件正在上传...')defdownload(self):print('文件正在下载...')
file_control_obj=FileControl()
file_control_obj.run()
以下为验证,反射中将输入输入字符创转化为方法
#代码同上,用来测试反射里面类型变化
classchoose:defrun(self):whileTrue:
cmd= input('请输入命令:').strip()ifhasattr(self,cmd):print(getattr(self,cmd)) #把字符串转化为方法
#>
print(type(getattr(self,cmd)))#
getattr(self,cmd)() #运行方法
else:print('输入有误')defload(self):print('load')defdown(self):print('down')
obj=choose()print(type(obj.load)) #
obj.run()