委托:如果我们要把方法当做参数来传递的话,就要用到委托。简单来说,委托的类型可以是赋值一个方法的引用. 可以把一个方法赋值过来,通过这个委托变量调用这个方法 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)方法。