zoukankan      html  css  js  c++  java
  • 面向对象之多态,多态性,反射,以及基于反射的可拔插设计

    多态

    一、什么多态?

    多态指的是一类事物有多种形态,比如
    动物有多种形态:人,狗,猪
    例如

    import abc  #创建抽象类 导入abc
    
    class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
        @abc.abstractmethod  			 #归一化设计
        def talk(self):
            pass
    
    class People(Animal): #动物的形态之一:人
        def talk(self):
            print('say hello')
    
    class Dog(Animal): #动物的形态之二:狗
        def talk(self):
            print('say wangwang')
    
    class Pig(Animal): #动物的形态之三:猪
        def talk(self):
            print('say aoao')
    
    文件也有多态性比如:
    文件有多种形态:文本文件,可执行文件
    import abc
    class File(metaclass=abc.ABCMeta): #同一类事物:文件
        @abc.abstractmethod
        def click(self):
            pass
    
    class Text(File): #文件的形态之一:文本文件
        def click(self):
            print('open file')
    
    class ExeFile(File): #文件的形态之二:可执行文件
        def click(self):
            print('execute file')
    
    多态性
    1.什么是多态性

    多态性是指在不考虑实例类型的情况下使用实例,多态性分为 静态多态性 和 动态多态性

    静态多态性:如任何类型都可以用运算符+进行运算

    动态多态性如下实例:

    peo=People()
    dog=Dog()
    pig=Pig()
    
    #peo、dog、pig都是动物,只要是动物肯定有talk方法
    #于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
    peo.talk()
    dog.talk()
    pig.talk()
    
    #更进一步,我们可以定义一个统一的接口来使用,动态的执行不同动物的talk方法
    def func(obj):
        obj.talk()
    
    二为什么要用多态性(多态性的好处)

    1.增加了程序的灵活性
      以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
     
     

    2.增加了程序额可扩展性
    通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用

    class H2O():  
        #水有多种形态冰,液态水,水蒸气
        	
        def __init__(self, name, temp):
                self.name = name
                self.temp = temp
    
        def turn_active(self):
            if self.temp < 0:
                print("我是 %s 我已经变成冰了!" % self.name)
            elif self.temp > 0 and self.temp < 100:
                print("我是液水")
            elif self.temp > 100:
                print("我是%s 我变成水蒸气了" % self.name)
    
    	
    	class Water(H2O):
    	    pass
    	
    	
    	class Iire(H2O):
    	    pass
    	
    	
    	class Vapor(H2O):
    	    pass
    	
    	
    	w1 = Water('水', 10) #生成各自的实例
    	i1 = Iire("冰", -100)
    	v1 = Vapor("水蒸气", 1000)
    	
    	
    	# ************
    	def func(obj): ##对于使用者来说,自己的代码根本无需改动
    	    obj.turn_active()
    	
    	
    	func(w1) #实例调用统一的接口来实行trun_active()方法
    

    二 反射

    1.什么反射:

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

    2.python面向对象中的反射:

    通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

    四个可以实现自省的函数 下列方法适用于类和对象(一切皆对象,类本身也是一个对象)[hasattr,getattr,setattr,delattr]

    hasattr(object,name)

    判断object中有没有一个name字符串对应的方法或属性
    

    getattr(object, name, default=None)

    获取对象的属性方法(Get a named attribute from an object)

    	def getattr(object, name, default=None): # known special case of getattr
    	    """
    	    getattr(object, name[, default]) -> value
    	
    	    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    	    When a default argument is given, it is returned when the attribute doesn't
    	    exist; without it, an exception is raised in that case.
    	    """
    	    pass
    

    setattr(x, y, v)

    def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.
    
    setattr(x, 'y', v) is equivalent to ``x.y = v''
    """
    pass
    

    delattr(x, y)

    def delattr(x, y): # real signature unknown; restored from __doc__
        """
        Deletes the named attribute from the given object.
    
        delattr(x, 'y') is equivalent to ``del x.y''
        """
        pass
    
    四个方法的使用演示
    class BlackMedium:
    	feture = 'Ugly'
    
        def __init__(self, name, addr):
            self.name = name
            self.addr = addr
    
        def sell_hourse(self):
            print('【%s】 正在卖房子,傻逼才买呢' % self.name)
    
        def rent_hourse(self):
            print('【%s】 正在租房子,傻逼才租呢' % self.name)
    
    
    
    b1=BlackMedium("黑中介","北京")
    print(hasattr(b1,"name")) #判断实例有没有name的这个属性
    
    func=getattr(b1,"sell_hourse")# 获得实例属性
    func()
    func1=getattr(b1,"sell_hoursedasd","没有这个属性") # default默认值
    print(func1)
    
    
    setattr(b1,"key","v1") #给对应实例添加数据属性
    
    print(b1.__dict__)
    
    
    delattr(b1,"key") #  删除实例的属性
    print(b1.__dict__)
    
    setattr(b1,"func2",lambda x:x+1)  #实例 设置 函数属性
    
    print(b1.func2(10))
    
    三、动态导入模块
    mm为当前目录下的文件夹下面有tt.py
    m = model_t = __import__("mm.tt")  # 只能导入第一层
    print(m)
    m.tt.test1()
    
    import importlib #使用模块 动态导入,推荐这种方法
    m2=importlib.import_module("mm.tt")
    print(m2)
    m2.test2()
    

    四、基于反射实现可拔插组件

    bob正在负责写FTP的客户端,但是最近他有大事,给耽误了,并且其他人需要用到这个ftp中的一些方法,这时候我们就需要用到反射

    客户端残次品代码

    	class FtpClient:
        def __init__(self,name):
            print("client ....")
            self.name=name
    

    调用者需要基于反射调用FTp的客户端,如下:

    from Ftp_client import *
    c1 = FtpClient("client")
    if hasattr(c1, "put"): #判断FTP客户端有没有put方法
        put_func = getattr(c1, "put") # 有就调用执行
        put_func()
    else:
        print("没有执行put 完成其他操作!") #没有do other things!
  • 相关阅读:
    洛谷【P1109 学生分组】 题解
    卡特兰数
    并查集
    深度优先搜索DFS;递归
    【71】序列模型和注意力机制
    c/c++ 常用的几个安全函数
    win32 Ui 编程 收集
    vc获取特殊路径(SpecialFolder)
    std::map 自定义排序
    16-----BBS论坛
  • 原文地址:https://www.cnblogs.com/zjcode/p/8718596.html
Copyright © 2011-2022 走看看