• Python的程序结构[1] -> 方法/Method[3] -> 魔术方法 __getattr__ 与代理模式


    __getattr__ 方法


    __getattr__ 方法当对象调用内部属性(包括方法等)且未找到对应属性的时候会调用的特殊方法。利用这一特性,可是对函数实现一个代理模式

    __getattr__方法实现代理模式

    当有一个类中已完成了许多函数的定义,而另外一个类要调用这些函数时,最直接的方法是使用代理,重载类的 __getattr__ 方法, 并在该方法内利用 getattr() 实现对被代理对象的属性获取,从而实现一个代理模式,简化代码。

    首先定义一个代理的对象类 Foo,实现几个方法,

     1 class Foo:
     2     def speak(self):
     3         print('Speak hello world')
     4 
     5     def act(self, action):
     6         print('Act', action)
     7 
     8     def eat(self, food, fruit):
     9         print('Eat', food, fruit)
    10 
    11     def place(self):
    12         print('Place things by Foo')

    现在,假设我们有两个类,一个不使用代理模式(NoProxy 类),一个使用代理模式(Proxy 类),需要实现相同的功能,

    对于不使用代理的类,在类中要完成 Foo 的方法调用则需要对这些方法分别定义新方法并调用,方式如下,

     1 class NoProxy:
     2     def __init__(self):
     3         self._foo = Foo()
     4 
     5     def speak(self):
     6         self._foo.speak()
     7 
     8     def act(self, action):
     9         self._foo.act(action)
    10 
    11     def eat(self, food, fruit):
    12         self._foo.eat(food, fruit)
    13 
    14     def watch(self):
    15         self.act('watching')

    在 NoProxy 类中,speak / act / watch 三个方法分别调用 Foo 中的方法,同时还有一个自己的 watch 方法,但如果当需要代理的方法很多时,每一个方法都要进行二次定义,将十分麻烦,为此可以使用代理模式(使用基类继承也可以,略有区别)进行代码的简化。

     1 class Proxy:
     2     def __init__(self):
     3         self._foo = Foo()
     4 
     5     def __getattr__(self, item):
     6         print('Use Proxy')
     7         return getattr(self._foo, item)
     8 
     9     def watch(self):
    10         self.act('Watching')
    11 
    12     def place(self):
    13         print('Place things by Proxy')

    从代码中可以看到,使用魔术方法 __getattr__ 可以实现一个简单的代理模式,当在 Proxy 类中搜索不到对应的属性或方法时(调用 __getattribute__ 方法),便会调用 __getattr__ 方法,此时则利用 getattr() 函数获取代理对象的对应方法再返回即可。

    接着分别对两个类进行方法的调用,并在最后调用一个代理类中已存在的方法,证明代理只有在搜索不到方法的时候才会起作用。

    1 for x in [NoProxy(), Proxy()]:
    2     x.speak()
    3     x.act('run')
    4     x.eat('rice', 'apple')
    5     x.watch()
    6 Proxy().place()

    最终,NoProxy 类输出的结果为,

    Speak hello world
    Act run
    Eat rice apple
    Act watching

    而 Proxy 类输出的结果为,

    Use Proxy
    Speak hello world
    Use Proxy
    Act run
    Use Proxy
    Eat rice apple
    Use Proxy
    Act Watching

    两者功能相同,但如果当代理对象的函数方法较多时,则使用代理模式能够使代码更加简洁。 最后,还可以看到当 Proxy 类和 Foo 类中的 place 方法都存在时,会优先使用 Proxy 类的方法。

    Place things by Proxy

    参考链接


    http://www.jianshu.com/p/09f88a11928f

  • 相关阅读:
    [BZOJ 3144][HNOI 2013] 切糕
    吴裕雄 python 机器学习——模型选择参数优化暴力搜索寻优GridSearchCV模型
    吴裕雄 python 机器学习——模型选择参数优化随机搜索寻优RandomizedSearchCV模型
    吴裕雄 python 机器学习——模型选择验证曲线validation_curve模型
    吴裕雄 python 机器学习——模型选择学习曲线learning_curve模型
    吴裕雄 python 机器学习——模型选择回归问题性能度量
    吴裕雄 python 机器学习——模型选择分类问题性能度量
    吴裕雄 python 机器学习——模型选择数据集切分
    吴裕雄 python 机器学习——模型选择损失函数模型
    吴裕雄 python 机器学习——数据预处理字典学习模型
  • 原文地址:https://www.cnblogs.com/stacklike/p/8098028.html
Copyright © 2020-2023  润新知