zoukankan      html  css  js  c++  java
  • Python开发基础-Day21多态与多态性、绑定方法和非绑定方法

    多态与多态性

    多态

    多态并不是一个新的知识

    多态是指一类事物有多种形态,在类里就是指一个抽象类有多个子类,因而多态的概念依赖于继承

    举个栗子:动物有多种形态,人、狗、猫、猪等,python的序列数据类型有字符串、列表、元组,文件的类型分为普通文件和可执行文件,人类又有多种形态,男女老少。。等等例子

     1 import abc
     2 class Animal(metaclass=abc.ABCMeta):    #模拟动物类
     3     @abc.abstractmethod
     4     def talk(self):
     5         pass
     6 class People(Animal):       #模拟人类
     7     def talk(self):
     8         print('say hello world')
     9 class Cat(Animal):          #模拟猫类
    10     def talk(self):
    11         print('say miaomiaomiao')
    12 class Dog(Animal):          #模拟狗类
    13     def talk(self):
    14         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:

     1 import abc
     2 class Animal(metaclass=abc.ABCMeta):    #模拟动物类
     3     @abc.abstractmethod
     4     def talk(self):
     5         pass
     6 class People(Animal):       #模拟人类
     7     def talk(self):
     8         print('say hello world')
     9 class Cat(Animal):          #模拟猫类
    10     def talk(self):
    11         print('say miaomiaomiao')
    12 class Dog(Animal):          #模拟狗类
    13     def talk(self):
    14         print('say wangwangwang')
    15 
    16 p1=People()
    17 c1=Cat()
    18 d1=Dog()
    19 
    20 def talk(obj):    #多态性
    21     obj.talk()
    22 talk(p1)
    23 talk(c1)
    24 talk(d1)

    多态性的优点1:以不变应万变,统一调用接口,使用者只用一种调用方式即可

    多态性的优点2:增加扩展性,比如上述代码再加一个Pig类,调用talk功能的方式不会改变,就是talk(Pig对象)

    绑定方法与非绑定方法

    类中定义的函数分为两类:绑定方法和非绑定方法

    绑定方法:绑定给谁就给谁用,可以是对象,也可以是类本身。

    绑定到对象的方法:

      定义:凡是在类中定义的函数(没有被任何装饰器修饰),都是绑定给对象的,无论有有没有传参

      给谁用:给对象用

      特点:例如obj.bar() 自动把obj当做第一个参数传入,因为bar中的逻辑就是要处理obj这个对象

    示例:

     1 class People:
     2     def __init__(self, name, weight, height):
     3         self.name = name
     4         self.weight = weight
     5         self.height = height
     6     def bmi(self):    #绑定到对象,需要传入对象的名字,而类本身是无法使用的,如果硬要使用,也需要把对象名字传进来
     7         print(self.weight / (self.height ** 2))
     8 f = People('bob', 70, 1.80)
     9 f.bmi()    #绑定对象使用的方法
    10 People.bmi(f)    #类使用需要传入对象名字

    绑定到类的方法:

      定义:在类中定义的,被classmethod装饰的函数就是绑定到类的方法

      给谁用:给类用

      特点:例如People.talk() 自动把类当做第一个参数传入,因为talk中的逻辑就是要处理类

    注意:自动传值只是使用者意淫的,属于类的函数,类可以调用,但是必须按照函数的规则来,在任何过程中都没有自动传值那么一说,传值都是事先定义好的,只不过使用者感知不到。

    示例1:

     1 class People:
     2     def __init__(self,name):
     3         self.name=name
     4     def bar(self):
     5         print('Object name:',self.name)
     6     @classmethod    #将方法绑定给类People
     7     def func(cls):  #传入的值只能是类的名字
     8         print('Class name:',cls)
     9 f=People('natasha')
    10 print(People.func)  #绑定给类
    11 print(f.bar)    #绑定给对象
    12 People.func()   #类调用绑定到类的方法
    13 f.func()    #对象调用绑定到类的方法,打印的依然是类的名字

    输出结果:

    1 <bound method People.func of <class '__main__.People'>>    #绑定到类的方法
    2 <bound method People.bar of <__main__.People object at 0x0000026FC4109B38>>    #绑定到对象的方法
    3 Class name: <class '__main__.People'>     #类调用返回类名
    4 Class name: <class '__main__.People'>     #对象调用返回类名

    非绑定方法:

    用staticmethod装饰器装饰的方法,非绑定方法不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已

    注意:没有传值的普通函数并不是非绑定方法,只有被staticmethod装饰的才是非绑定方法。

    示例

     1 import hashlib
     2 import pickle
     3 import os
     4 # 模拟注册,生成一个唯一id标识
     5 student_path=r'C:UsersMr.chaiDesktopPythonProject笔记2017.7.6db'
     6 
     7 class People:
     8     def __init__(self,name,sex,user_id):
     9         self.name=name
    10         self.sex=sex
    11         self.user_id=user_id
    12         self.id=self.create_id()
    13     def tell_info(self):    #打印所有信息
    14         print('''
    15         =====%s info=====
    16         id:%s
    17         name:%s
    18         sex:%s
    19         user_id:%s
    20         ''' %(self.name,self.id,self.name,self.sex,self.user_id))
    21     def create_id(self):    #生成一个id号,对name、sex和user_id进行哈希
    22         m=hashlib.md5()
    23         m.update(self.name.encode('utf-8'))
    24         m.update(self.sex.encode('utf-8'))
    25         m.update(str(self.user_id).encode('utf-8'))
    26         return m.hexdigest()
    27     def save(self):     #将id号序列化到文件,以id号为文件名字
    28         idfile_path=student_path+'\'+self.id
    29         with open(idfile_path,'wb') as f:
    30             pickle.dump(self,f)
    31     @staticmethod       #反序列化程序,是一个非绑定方法,无关类和对象
    32     def get_all():
    33         res=os.listdir(student_path)
    34         for item in res:
    35             file_path = r'%s\%s' %(student_path,item)
    36             with open(file_path,'rb') as f:
    37                 obj = pickle.load(f)
    38                 obj.tell_info()

    测试:生成序列化文件

     1 #实例化对象
     2 p1=People('natasha','male',370283111111111111)
     3 p2=People('hurry','male',3702832222222222222)
     4 p3=People('bob','male',3702833333333333333)
     5 #查询唯一标识
     6 print(p1.id)
     7 print(p2.id)
     8 print(p3.id)
     9 #对象pickle序列化
    10 p1.save()
    11 p2.save()
    12 p3.save()
    13 
    14 查询输出:
    15 b4ea1e1f1e45428ee16035e101caac7b
    16 274496ab60ceea8bf4c89c841d2b225c17 0defdb74fdee00f2164839343c16a7d7

    生成文件

    反序列化:

     1 p1.get_all()
     2 # p2.get_all()
     3 # p3.get_all()
     4 
     5 输出结果
     6 
     7         =====bob info=====
     8         id:0defdb74fdee00f2164839343c16a7d7
     9         name:bob
    10         sex:male
    11         user_id:3702833333333333333
    12         
    13 
    14         =====hurry info=====
    15         id:274496ab60ceea8bf4c89c841d2b225c
    16         name:hurry
    17         sex:male
    18         user_id:3702832222222222222
    19         
    20 
    21         =====natasha info=====
    22         id:b4ea1e1f1e45428ee16035e101caac7b
    23         name:natasha
    24         sex:male
    25         user_id:370283111111111111
    26         

    绑定到类的方法应用

  • 相关阅读:
    Sum Root to Leaf Numbers 解答
    459. Repeated Substring Pattern
    71. Simplify Path
    89. Gray Code
    73. Set Matrix Zeroes
    297. Serialize and Deserialize Binary Tree
    449. Serialize and Deserialize BST
    451. Sort Characters By Frequency
    165. Compare Version Numbers
    447. Number of Boomerangs
  • 原文地址:https://www.cnblogs.com/zero527/p/7127551.html
Copyright © 2011-2022 走看看