多态 抽象类 鸭子类型 classmethod 和 staticmethod isinstance 和 issubclass 反射
1.多态
1.什么是多态?
-多态指的同一种类型的事物的不同形态。
2.多态的目的:
-'多态'也成为'多态性',目的是为了再不知道对象的具体类型情况下,统一对象的调用方法的规范(比如写字)
-多态的表现形式之一就是 继承
-先抽象,在继承
父类:定制一套统一的规范,(比如:方法统一)
子类:遵循父类的统一的规范。(比如子类遵循父类方法名统一的)
注意:在python中不会强制限制子类的必须要遵循父类的规范,所以出现了抽象类。
#动物类
class Animal:######这个就是统一的规范
#方法吃
def eat(self):
pass
#方法 叫
def speak(self):
pass
#猪类
class Pig(Animal):
def eat(self):####这个就是根据父类的规范来操作的
print('baiji...')
def speak(self):
print('哼哼哼...')
#猫
class Cat(Animal):
def eat(self):
print('yaojiyaoji')
def speak(self):
print('喵喵...')
#狗类
class Dog(Animal):
def eat(self):
print('tianjitianji')
def speak(self):
print('汪汪...')
animal1 = Dog()
animal2 = Cat()
animal3 = Pig()
animal1.eat()
下面这个是一个反面的教材,这个就是个错误的
class Animal:######这个就是统一的规范
#方法吃
def eat(self):
pass
#方法 叫
def speak(self):
pass
#猪类
class Pig(Animal):
def eat(self):
print('baiji...')
def speak(self):
print('哼哼哼...')
#猫
class Cat(Animal):
def chi(self):######和父类的规范要求不一样
print('yaojiyaoji')
def tell(self):
print('喵喵...')
#狗类
class Dog(Animal):
def chi_1(self):######和父类的规范要求不一样
print('tianjitianji')
def jiao(self):
print('汪汪...')
2.抽象类
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('biajiji')
def speak(self):
print('哼哼...')
print(Pig.__dict__)
print(Animal.__dict__)
pig_obj = Pig()
3.鸭子类型
1.什么是鸭子类型?
-不同的对象,只要长的像鸭子,动作行为像鸭子,那他就是鸭子
-鸭子类型是多态的一种表现形式
2.为什么有鸭子类型?
-不同的对象,先抽象出相同类型的方法,给他们制定一套统一的规范。
-所有的类,在定义时都按照统一的规范进行编写
-在定义之前,先定义一套鸭子类型规范
3.多态的三种表现形式:
1.继承父类
-耦合度高,程序的可扩展性低
2.继承抽象类
-耦合度极高,程序的可扩展性极低
3.鸭子类型‘
-耦合度低,程序的可扩展性高
注意:在python中,强烈推荐鸭子类型
#猪类
class Pig:
def eat(self):
print('biajiji')
def speak(self):
print('哼哼...')
#猫类
class Cat:
def eat(self):
print('yaojiyaoji...')
def speak(self):
print('miaomiao...')
#狗类
class Dog:
def eat(self):
print('tianjitianji...')
def speak(self):
print('汪汪...')
- 鸭子类型规范::
- eat_fish:
- swimming:
- class Duck1:####这个就是鸭子类型
def eat_fish(self):
pass
def swimming(self):
pass
- class HCY:
def eat_fish(self):
pass
def swimming(self):
pass
以上的是鸭子类型,这个类型跟继承父类,比没有父类的规范要求
跟抽象类的比,没有父类的导入模块的要求
多态的炫技
#猪类
class Pig:
def eat(self):
print('biajiji...')
def speak(self):
print('hengheng...')
#猫类
class Cat:
def eat(self):
print('hengheng...')
def speak(self):
print('miaomiao...')
#狗类
class Dog:
def eat(self):
print('tianjitianji')
def speak(self):
print('wangwang...')
dog = Dog()
pig = Pig()
cat = Cat()
#多态之炫技
def SPEAK(animal):
animal.speak()
SPEAK(dog)
SPEAK(cat)
>>>>>>>>>>>>>>>>>
wangwang...
miaomiao...
str1 = 'tank is very handsome!'
def Len(obj):
return obj.__len__()
print(Len(str1))###具体的一个字符串是一个对象,对象自己的内置方法
print(len(str1))
>>>>>>>>>>>>>>>>>
22
22
4.classmethod 和staticmethod
-都是python解释器内置的装饰器
classmethod:
-是一个装饰器,给在类内部定义方法中装饰,将类内部方法变为“类的绑定方法”
staticmethod
-翻译:静态方法
-是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为“非绑定方法”
对象的绑定方法:
-由对象来调用,由谁来调用,会将对象当作第一个参数传入;
类的绑定方法:
-由类来调用,由谁来调用,会将类作为第一个参数来传入;
非绑定方法:
-可以由对象或者类来调用,谁来调用都是一个普通方法(普通函数),方法需要接收几个参数,就传入几个。
1.classmethod
#校验查看隐私的信息
class DB:
__data = 'tank is very handsome!'
def __init__(self,user,pwd,role):
self.user = user
self.pwd = pwd
self.role = role
def check_db(self):
if self.user == 'tank' and self.pwd == '123' and self.role == 'admin':
print('检验通过')
print(self.__class__.__data)
return self.__class__.__data
##__class__ 查看当前对象的类
db_obj = DB('tank','123','admin')
db_obj.check_db()
>>>>>>>>>>>>>>>>>>>
检验通过
tank is very handsome!
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):
obj = cls(user,pwd,role)#这个是类的实例化产生一个对象
#查看数据前,必须通过校验
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')
>>>>>>>>>>>>>>>>>
校验通过
tank is very handsome!
import uuid :用于产生随机字符串的模块
-具体是由时间戳及某种算法组合而成,会产生一串世界上独一无二字符串
-print(uuid.uuid4()) #####产生的是一串字符串
2.staticmethod
class Foo:
@staticmethod #####变成一种非绑定的方法
def func(res):
print(res)
obj = Foo()
#对象调用非绑定方法
obj.func(123)
###结果是123
Foo.func(1234)
>>>>>>>>
1234
如果没有@staticmethod
class Foo:
def func(res):
print(res)
Foo.func(1234)#####类调用的就是一个普通的函数 res需要一个实参
>>>>>>>>>>>>>
1234
class Foo:
def func(self,res):
print(res)
obj = Foo()
#对象调用非绑定方法
obj.func(123) ####对象的调用的是把自身作为第一个值传入,需要2个参数self,res
>>>>>>>>>>>>
123
5.isinstance issubclass
-这两个都是python的内置模块
-isinstance :判断一个对象是否是另一个类的实例。
-如果是:True
-如果不是:False
-issubclass:判断一个类是否是另一个类的子类
-如果是:True
-如果不是:False
class Foo:
pass
class Goo:
pass
goo_obj = Goo()
foo_obj = Foo()
print(isinstance(foo_obj,Foo))
print(isinstance(goo_obj,Foo))
>>>>>>>>>>>>>>>>
True
False
class Foo:
pass
class Goo(Foo):
pass
class Hoo:
pass
print(issubclass(Goo,Foo))
print(issubclass(Hoo,Foo))
>>>>>>>>>>>>>>>
True
False
6.反射
-反射指的是通过’字符串''对对象的属性进行操作
-hasattr :通过'字符串'判断对象的属性或方法是否存在
-getattr:通过'字符串'获取对象的属性或者方法
-setattr:通过'字符串'设置对象的属性或方法
-delattr: 通过'字符串'删除对象的属性或者方法
注意:反射的4个方法是python的内置的
###hasattr
class Foo:
def __init__(self,x,y):
self.x = x
self.y = y
foo_obj = Foo(10,20)
#hasattr
print(hasattr(foo_obj,'x'))
print(hasattr(foo_obj,'y'))
print(hasattr(foo_obj,'z'))
>>>>>>>>>>>>>>>>>>>>>>>
True
True
False
###getattr
class Foo:
def __init__(self,x,y):
self.x = x
self.y = y
foo_obj = Foo(10,20)
res = getattr(foo_obj,'x')
print(res)
res1 = getattr(foo_obj,'z','默认值')###z不存在,可以在后面加一个默认值,字符串类型的
print(res1)
>>>>>>>>>>>>>>
10
123
####setattr
class Foo:
def __init__(self,x,y):
self.x = x
self.y = y
foo_obj = Foo(10,20)
setattr(foo_obj,'z',30) #这个setattr的有过这个字符串有值 再设置就会更新,如果是没有值的 会新创建一个属性
print(hasattr(foo_obj,'z'))
>>>>>>>>>>>>>>>>>>>>>>
True
###delattr
class Foo:
def __init__(self,x,y):
self.x = x
self.y = y
foo_obj = Foo(10,20)
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()
break
else:
print('输入有误')
def upload(self):
print('文件正在上传...')
def download(self):
print('文件正在下载...')
filecontrol_obj = FileControl()
filecontrol_obj.run()
>>>>>>>>>>>>>>>>>>
请输入upload 或者download:sffjf
输入有误
请输入upload 或者download:dfgf
输入有误
请输入upload 或者download:a1223
输入有误
请输入upload 或者download:download
文件正在下载...
Process finished with exit code 0