DAY34 多态与多态性、绑定方法和非绑定方法
来源:互联网 发布:防范网络诈骗标语 编辑:程序博客网 时间:2024/06/05 14:38
多态与多态性
多态
多态并不是一个新的知识
多态是指一类事物有多种形态,在类里就是指一个抽象类有多个子类,因而多态的概念依赖于继承
举个栗子:动物有多种形态,人、狗、猫、猪等,python的序列数据类型有字符串、列表、元组,文件的类型分为普通文件和可执行文件,人类又有多种形态,男女老少。。等等例子
import abcclass Animal(metaclass=abc.ABCMeta): #模拟动物类 @abc.abstractmethod def talk(self): passclass People(Animal): #模拟人类 def talk(self): print('say hello world')class Cat(Animal): #模拟猫类 def talk(self): print('say miaomiaomiao')class Dog(Animal): #模拟狗类 def talk(self): print('say wangwangwang')
动物都能叫,所以人类、猫类、狗类也都可以叫,只不过叫的方式不一样。
多态性:
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用到不同功能的函数。
在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)
多态性实际上就是一个接口,即调用同一个函数,产生不同的结果。
示例1:使用数据对象的len属性统计对象长度
1 def func(obj):2 obj.__len__()3 func('hello')4 func([1,2,3,4])5 func(('a','b','c'))
示例2:
import abcclass Animal(metaclass=abc.ABCMeta): #模拟动物类 @abc.abstractmethod def talk(self): passclass People(Animal): #模拟人类 def talk(self): print('say hello world')class Cat(Animal): #模拟猫类 def talk(self): print('say miaomiaomiao')class Dog(Animal): #模拟狗类 def talk(self): print('say wangwangwang')p1=People()c1=Cat()d1=Dog()def talk(obj): #多态性 obj.talk()talk(p1)talk(c1)talk(d1)
多态性的优点1:以不变应万变,统一调用接口,使用者只用一种调用方式即可
多态性的优点2:增加扩展性,比如上述代码再加一个Pig类,调用talk功能的方式不会改变,就是talk(Pig对象)
绑定方法与非绑定方法
类中定义的函数分为两类:绑定方法和非绑定方法
绑定方法:绑定给谁就给谁用,可以是对象,也可以是类本身。
绑定到对象的方法:
定义:凡是在类中定义的函数(没有被任何装饰器修饰),都是绑定给对象的,无论有有没有传参
给谁用:给对象用
特点:例如obj.bar() 自动把obj当做第一个参数传入,因为bar中的逻辑就是要处理obj这个对象
示例:
class People: def __init__(self, name, weight, height): self.name = name self.weight = weight self.height = height def bmi(self): #绑定到对象,需要传入对象的名字,而类本身是无法使用的,如果硬要使用,也需要把对象名字传进来 print(self.weight / (self.height ** 2))f = People('bob', 70, 1.80)f.bmi() #绑定对象使用的方法People.bmi(f) #类使用需要传入对象名字
绑定到类的方法:
定义:在类中定义的,被classmethod装饰的函数就是绑定到类的方法
给谁用:给类用
特点:例如People.talk() 自动把类当做第一个参数传入,因为talk中的逻辑就是要处理类
注意:自动传值只是使用者意淫的,属于类的函数,类可以调用,但是必须按照函数的规则来,在任何过程中都没有自动传值那么一说,传值都是事先定义好的,只不过使用者感知不到。
示例1:
class People: def __init__(self,name): self.name=name def bar(self): print('Object name:',self.name) @classmethod #将方法绑定给类People def func(cls): #传入的值只能是类的名字 print('Class name:',cls)f=People('natasha')print(People.func) #绑定给类print(f.bar) #绑定给对象People.func() #类调用绑定到类的方法f.func() #对象调用绑定到类的方法,打印的依然是类的名字
输出结果:
<bound method People.func of <class '__main__.People'>> #绑定到类的方法<bound method People.bar of <__main__.People object at 0x0000026FC4109B38>> #绑定到对象的方法Class name: <class '__main__.People'> #类调用返回类名Class name: <class '__main__.People'> #对象调用返回类名
非绑定方法:
用staticmethod装饰器装饰的方法,非绑定方法不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已
注意:没有传值的普通函数并不是非绑定方法,只有被staticmethod装饰的才是非绑定方法。
示例
import hashlibimport pickleimport os# 模拟注册,生成一个唯一id标识student_path=r'C:\Users\Mr.chai\Desktop\PythonProject\笔记\2017.7.6\db'class People: def __init__(self,name,sex,user_id): self.name=name self.sex=sex self.user_id=user_id self.id=self.create_id() def tell_info(self): #打印所有信息 print(''' =====%s info===== id:%s name:%s sex:%s user_id:%s ''' %(self.name,self.id,self.name,self.sex,self.user_id)) def create_id(self): #生成一个id号,对name、sex和user_id进行哈希 m=hashlib.md5() m.update(self.name.encode('utf-8')) m.update(self.sex.encode('utf-8')) m.update(str(self.user_id).encode('utf-8')) return m.hexdigest() def save(self): #将id号序列化到文件,以id号为文件名字 idfile_path=student_path+'\\'+self.id with open(idfile_path,'wb') as f: pickle.dump(self,f) @staticmethod #反序列化程序,是一个非绑定方法,无关类和对象 def get_all(): res=os.listdir(student_path) for item in res: file_path = r'%s\%s' %(student_path,item) with open(file_path,'rb') as f: obj = pickle.load(f) obj.tell_info()
测试:生成序列化文件
#实例化对象p1=People('natasha','male',370283111111111111)p2=People('hurry','male',3702832222222222222)p3=People('bob','male',3702833333333333333)#查询唯一标识print(p1.id)print(p2.id)print(p3.id)#对象pickle序列化p1.save()p2.save()p3.save()查询输出:b4ea1e1f1e45428ee16035e101caac7b274496ab60ceea8bf4c89c841d2b225c17 0defdb74fdee00f2164839343c16a7d7
生成文件
反序列化:
p1.get_all()# p2.get_all()# p3.get_all()输出结果 =====bob info===== id:0defdb74fdee00f2164839343c16a7d7 name:bob sex:male user_id:3702833333333333333 =====hurry info===== id:274496ab60ceea8bf4c89c841d2b225c name:hurry sex:male user_id:3702832222222222222 =====natasha info===== id:b4ea1e1f1e45428ee16035e101caac7b name:natasha sex:male user_id:370283111111111111
- DAY34 多态与多态性、绑定方法和非绑定方法
- 绑定和非绑定方法
- 绑定方法与非绑定方法
- 面向对象--绑定方法与非绑定方法
- python类的绑定方法与非绑定方法
- 关于Python绑定方法和非绑定方法的思考
- python绑定方法和无绑定方法
- 【搬家】【Python】Python 中类的绑定方法与非绑定方法释疑
- 方法调用绑定--前期绑定和后期绑定
- WordPress绑定多个域名和禁止搜索引擎收录非主域名的方法
- Java中的方法绑定及多态
- React与ES6(三)ES6类和方法绑定
- Java方法的动态绑定与静态绑定
- java中多态性与动态绑定
- iOS多态性 动态绑定 与动态类型
- ASP.NET GridView绑定数据方法和转换绑定数据
- Service服务(非绑定与绑定)
- datagridview 绑定数据和非绑定模式
- mvc.net分页查询案例——PagedList
- spring-boot问题1:搭建spring-boot项目报错 Error parsing lifecycle processing instructions
- mvc.net分页查询案例——PagerExtension
- python复习笔记
- FZUOJ 2214
- DAY34 多态与多态性、绑定方法和非绑定方法
- 人脸对齐
- mvc.net分页查询案例——mvc-paper.css
- HTML+CSS编写静态网站-28 调整标题和导航
- 不破楼兰终不还
- ORACLE回收站机制介绍
- mvc.net分页查询案例——DLL数据访问层(HouseDLL.cs)
- c++面试题
- 缓存穿透优化