代理属性访问

代理属性访问通常作为类继承的一种替代,最简单的代理属性访问代码如下:

class A:
    def spam(self, x):
        pass

    def foo(self):
        pass

class B:
    def __init__(self):
        self._a = A()

    def spam(self, x):
        # Delegate to the internal self._a instance
        return self._a.spam(x)

    def foo(self):
        # Delegate to the internal self._a instance
        return self._a.foo()

    def bar(self):
        pass

如果只有几个方法需要代理,可以实现类的__getattr__方法,如下:

class A:
    def spam(self, x):
        pass

    def foo(self):
        pass

class B:
    def __init__(self):
        self._a = A()

    def bar(self):
        pass

    # Expose all of the methods defined on class A
    def __getattr__(self, name):
        return getattr(self._a, name)

>>> b = B()
>>> b.bar()
>>> b.spam(42)

另一个示例:

class Proxy:
    def __init__(self, obj):
        self._obj = obj

    # Delegate attribute lookup to internal obj
    def __getattr__(self, name):
        print('getattr', name)
        return getattr(self._obj, name)

    # Delegate attribute assignment
    def __setattr__(self, name, value):
        if name.startswith('_'):
            super().__setattr__(name, value)
        else:
            print('setattr:', name, value)
            setattr(self._obj, name, value)

    # Delegate attribute deletion
    def __delattr__(self, name):
        if name.startswith('_'):
            super().__delattr__(name)
        else:
            print('delattr:', name)
            delattr(self._obj, name)

class Spam:
    def __init__(self, x):
        self.x = x
    def bar(self, y):
        print('Spam.bar:', self.x, y)

>>> s = Spam(2)
>>> p = Proxy(s)
>>> print(p.x)
getattr x
2
>>> p.bar(3)
getattr bar
Spam.bar: 2 3
>>> p.x = 37
setattr: x 37

常见的约定是,代理只能委派不以下划线开头的属性(即代理仅公开所保留实例的“公共”属性)。
同样重要的是要强调__getattr __()方法通常不适用于大多数以双下划线开头和结尾的特殊方法。如下:

class ListLike:
    def __init__(self):
        self._items = []

    def __getattr__(self, name):
        return getattr(self._items, name)

>>> a = ListLike()
>>> a.append(2)
>>> a.insert(0, 1)
>>> a.sort()
>>> len(a)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: object of type 'ListLike' has no len()
>>> a[0]
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: 'ListLike' object does not support indexing
>>>

若要实现如len, 索引等方法,则必须实现如__len__,__getitem__,__setitem__,__delitem__等方法。

原文地址:https://www.cnblogs.com/jeffrey-yang/p/12142481.html

时间: 2024-10-14 08:10:01

代理属性访问的相关文章

ie8 报错:意外地调用了方法或属性访问

在某场景中一句简单的js: $("#changeOption").text("增加"); 在 IE8 下面报错:'意外地调用了方法或属性访问' 改成:$("#changeOption").html("增加"); 报同样的错. 改成:document.getElementById('changeOption').innerText="增加"; 同样报错:"未知的运行时错误" 最后改成:$(

Python类属性访问的魔法方法

Python类属性访问的魔法方法: 1. __getattr__(self, name)- 定义当用户试图获取一个不存在的属性时的行为 2. __getattribute__(self, name)- 定义当该类的属性被访问时的行为 注意:当__getattr__与__getattribute__同时重写时,访问属性时,优先调用__getattribute__,只有当被访问的属性不存在时才触发__getattr__ 3. __setattr__(self, name, value)- 定义当一个

14.C#属性访问器、命名空间、pragma指令(七章7.3-7.5)

看到一些零星的知识片,今天就用自己的理解说明下,也是因为太简单了,一下就过的,也是我们日常开发中常用.留下一个脚印,当书不在手上的,也能翻出来看看.说下属性访问器.命名空间和pragma指令. 属性访问器在01.C#数据类型.排序.过滤(一章1.1-1.2)有所提到,在C#3后可以使用修饰符去修饰属性的取值和赋值,也可以使用加入一些验证,如下: 1 class Plant 2 { 3 private double Height = 0.0; 4 5 //是否需要修剪 6 public bool

使用SSH代理实现访问国外网址

1. 在SSH服务器端创建用户: useradd -M -s /bin/false username passwd username 2. 安装myentunnel软件 (Linux用户可使用:ssh -CfNg -D 127.0.0.1:7070 用户名@服务器地址) 3. 打开Firefox 4. 修改Firefox代理设置: 5. 以管理员身份运行myentunnel或者参考下图: 6. 填入在SSH服务器端建立的用户名和密码 (useradd -m username) 7. 点击conn

javascript的属性访问

可以通过点运算符(.)来访问引用的属性.只要在点运算符之后书写属性名,就能够读取相应的属性值. //js>print(obj.x) 3 如果属性的值是一个对象,可以像下面这样通过多次点运算符来读取其属性. js>var obj2={pos:{x:3,y:4}}; js>print(obj.pos.x); 3 如果赋值给尚不存在的属性名,则将新建该属性并对其赋值. js>obj.z=5; js>print(obj.z); 5 属性访问(括号方式) js>print(obj

SEAndroid安全机制对Android属性访问的保护分析

Android系统通过属性暴露设备和运行时信息,并且可以通过设置属性来控制系统行为.因此,属性也像文件一样,是一种需要保护的资源.在启用SEAndroid之前,敏感属性只能被预先设定的进程进行设置.启用SEAndroid之后,敏感属性会进一步被SEAndroid安全策略保护.这样就可以更有效地保护系统属性了.在本文中,我们就详细分析SEAndroid安全机制对Android属性设置保护提供的支持. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 在分析SE

魔法方法:属性访问

__getattr__(self,name) 当用户试图访问name,而name属性不存在时就会调用getattr __getattribute__(self,name) 当用户试图访问name时就会调用getattribute __setattr__(self,name,value)当name被设置为value的时候就会调用setattr __delattr__(self,name)当name属性被删除时就会调用delattr 只有重写以上四个魔法方法,就可以改变属性访问

Python学习之属性访问与描述符详解

在Python开发中,对于一个对象的属性访问,我们一般采用的是点(.)属性运算符进行操作.例如,有一个类实例对象 foo ,它有一个 name 属性,那便可以使用 foo.name 对此属性进行访问.一般而言,点(.)属性运算符比较直观,也是我们经常碰到的一种属性访问方式.然而,在点(.)属性运算符的背后却是别有洞天,值得我们对对象的属性访问进行探讨. 在进行对象属性访问的分析之前,我们需要先了解一下对象怎么表示其属性.为了便于说明,本文以新式类为例.有关新式类和旧式类的区别,大家可以查看Pyt

045魔法方法:属性访问

属性访问:__getattr__(self,name)  定义当用户试图获取一个不存在的属性时的行为 __getattribute__(self,name)  定义当该类的属性被访问时的行为 __setattr__(self,name,value)  定义当用一个属性被设置时的行为 __delattr__(self,name)  定义当用一个属性被删除时的行为 例:>>> class C:  ...     def __getattribute__(self, name):