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

    多态与多态性

    多态

    多态并不是一个新的知识

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

    举个例子:动物有多种形态,人、狗、猫、猪等,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         
  • 相关阅读:
    C++编程入门题目--No.5
    C++编程入门题目--No.4
    C++编程入门题目--No.3
    C++编程入门题目--No.2
    C++入门编程题目 NO.1
    深度使用魅族16T后的评价(本人魅友,绝对客观公正,不要盲目的为手机厂商辩护,想想从当初到现在,魅族正在一步步背离自己的信仰,有问题,解决问题才能有更好的发展)
    ACM及各类程序竞赛专业术语
    python刷LeetCode:3.无重复字符的最长子串
    python刷LeetCode:2.两数相加
    python刷LeetCode:1.两数之和
  • 原文地址:https://www.cnblogs.com/chenqizhou/p/7200889.html
Copyright © 2011-2022 走看看