python委托模式详细解释(__getattr__)以及字段,属性,方法的涉及总结

委托:如果我们要把方法当做参数来传递的话,就要用到委托。简单来说,委托的类型可以是赋值一个方法的引用. 可以把一个方法赋值过来,通过这个委托变量调用这个方法 python函数是能作为参数输入函数的,这个相当于c里面的委托,将一个函数封装到一个委托对象里

首先我们看这个函数

__getattr__

getattr(object, name[, default])

  • object -- 对象。
  • name -- 字符串,对象属性。
  • default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。

该函数属于反射操作,用于获取 object 中名为 name 的属性(name 是以字符串表示的属性名), getattr(x, 'foobar') 等效于 x.foobar。如果 object 中含有 name 属性,则返回该属性;如果 object 没有 name 属性,则返回 default(如果提供),否则抛出 AttributeError 异常。

对于字段属性,会直接返回值;对于方法属性,会返回其引用(通过引用可调用方法属性)。

#字段包括普通字段和静态字段
class Province:
    # 静态字段
    country = '中国'
    def __init__(self, name):
        # 普通字段
        self.name = name
# 直接访问普通字段
obj = Province('河北省')
print obj.name
# 直接访问静态字段
Province.country

 

class ObjectDict(dict):
    def __init__(self, *args, **kwargs):
        super(ObjectDict, self).__init__(*args, **kwargs)

    def __getattr__(self, name):
        value =  self[name]
        if isinstance(value, dict):
            value = ObjectDict(value)
        return value

if __name__ == '__main__':
    od = ObjectDict(asf={'a': 1}, d=True)
    print od.asf
    print od.asf.a
    print od.d
>>>{'a':1}
>>>1
>>>True

 

#方法包括普通方法、静态方法和类方法
 三种方法在内存中都归属于类,区别在于调用方式不同。
普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
静态方法:由类调用;无默认参数;
class Foo:
    def __init__(self, name):
        self.name = name
    def ord_func(self):
        """ 定义普通方法,至少有一个self参数 """
        # print self.name
        print '普通方法'
    @classmethod
    def class_func(cls):
        """ 定义类方法,至少有一个cls参数 """
        print '类方法'
    @staticmethod
    def static_func():
        """ 定义静态方法 ,无默认参数"""
        print '静态方法'
# 调用普通方法
f = Foo()
f.ord_func()
# 调用类方法
Foo.class_func()
# 调用静态方法
Foo.static_func()
相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。
不同点:方法调用者不同、调用方法时自动传入的参数不同。

 

#属性(普通方法的变种)
class Foo:
    def func(self):
        pass
    # 定义属性
    @property
    def prop(self):
        pass
# ############### 调用 ###############
foo_obj = Foo()
foo_obj.func()#这叫调用方法
foo_obj.prop   #调用属性
-------------------------
由属性的定义和调用要注意一下几点:
定义时,在普通方法的基础上添加 @property 装饰器;
定义时,属性仅有一个self参数
调用时,无需括号
           方法:foo_obj.func()
           属性:foo_obj.prop
----------------------------------
属性的定义有两种方式:
装饰器 即:在方法上应用装饰器
静态字段 即:在类中定义值为property对象的静态字段           
经典类具有一种@property装饰器
新式类(Object) 具有三种@property装饰器
class Goods(object):
    @property
    def price(self):
        print '@property'
    @price.setter
    def price(self, value):
        print '@price.setter'
    @price.deleter
    def price(self):
        print '@price.deleter'
# ############### 调用 ###############
obj = Goods()
obj.price          
# 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 123    
# 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数
del obj.price      
# 自动执行 @price.deleter 修饰的 price 方法

 

class Wrapper:
    def __init__(self, obj):
        self.wrapper = obj
        print self.wrapper
        print type(self.wrapper)
        print"-"*100
 
    def __getattr__(self, item):
        print("trace:", item)
        return getattr(self.wrapper, item)
 
 
if __name__ == '__main__':
    x = Wrapper([1, 2, 3, 4])
    x.append(35)
    x.remove(2)
    print(x.wrapper)  # [1,3,4,35]

 在__init__(self,obj)方法中传入一个被委托对象。 通过重写__getattr__(self,item)方法,拦截外部对象的属性调用 在__getattr__(self,item)中,将拦截到的属性,让被委托对象去使用。 python 中的属性概念,和Java中的属性概念是不同的。Java中的属性,就是指类中定义的成员变量,绝对不包含方法。而在python中,任何能以obj.xx形式调用的东西,全部可以称为属性。无论是方法,还是变量,还是对象。 所以上述代码中调用x.append(N),实际上是让x的属性wrapper去调用append(N)方法。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值