python委托模式详细解释(__getattr__)以及字段,属性,⽅
法的涉及总结
委托:如果我们要把⽅法当做参数来传递的话,就要⽤到委托。简单来说,委托的类型可以是赋值⼀个⽅法的引⽤. 可以把⼀个⽅法赋值过来,通过这个委托变量调⽤这个⽅法 python函数是能作为参数输⼊函数的,这个相当于c⾥⾯的委托,将⼀个函数封装到⼀个委托对象⾥
python单例模式⾸先我们看这个函数
__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
# 直接访问静态字段
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()
# 调⽤类⽅法
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)
print(x.wrapper)  # [1,3,4,35]
在__init__(self,obj)⽅法中传⼊⼀个被委托对象。 通过重写__getattr__(self,item)⽅法,拦截外部对象的属性调⽤ 在
__getattr__(self,item)中,将拦截到的属性,让被委托对象去使⽤。 python 中的属性概念,和Java中的属性概念是不同的。Java中的属性,就是指类中定义的成员变量,绝对不包含⽅法。⽽在python中,任何能以形式调⽤的东西,全部可以称为属性。⽆论是⽅法,还是变量,还是对象。 所以上述代码中调⽤x.append(N),实际上是让x的属性wrapper去调⽤append(N)⽅法。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。

发表评论