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!
  • 相关阅读:
    Vasya and Endless Credits CodeForces
    Dreamoon and Strings CodeForces
    Online Meeting CodeForces
    数塔取数 基础dp
    1001 数组中和等于K的数对 1090 3个数和为0
    1091 线段的重叠
    51nod 最小周长
    走格子 51nod
    1289 大鱼吃小鱼
    POJ 1979 Red and Black
  • 原文地址:https://www.cnblogs.com/zjcode/p/8718596.html
Copyright © 2011-2022 走看看