Python魔法方法(magic method)细解几个常用魔法方法(下)

接上文,再介绍最后几个常用的魔法方法。

 

关于__dict__:

先上个例子:

class Test(object):
    fly = True

    def __init__(self, age):
        self.age = age

 

__dict__魔法方法可以被称为系统,他是存储各分层属性的魔法方法。__dict__中,键为属性名,值为属性本身。可以这样理解,在平时我们给类和实例定义的那些属性,都会被存储到__dict__方法中用于读取。而我们平时使用的类似这样的语法Test.fly 其实就是调用了类属性,同样可以写成Test.__dict__['fly']。除了类属性,还有实例属性。当我们用类实例化一个实例,例如上文我们使用p = Test(2)实例化类Test,p也会具有__dict__属性。这里会输出:

 

{'age': 2}

 

由上可以发现,python中的属性是进行分层定义的。/object/Test/p这样一层一层下来的。当我们需要调用某个属性的时候,python会一层一层往上面遍历上去。先从实例,然后实例的__class__的__dict__,然后是该类的__base__。这样__dict__一路找上去。如果最后都没有找到,就抛出AttributeError错误。

这里可以延伸一下,没记错的话,我前面有篇文章讲了一个方法__slot__。__slots__方法就是通过限制__dict__,只让类实例初始化__slots__里面定义的属性,而且让实例不再拥有__dict__方法,来达到节约内存的目的。我将会就上面的那个例子重写一下,来说明这个问题。

 

 class Test(object):
     __slots__ = ['age']

     fly = True

     def __init__(self, age):
         self.age = age

 

output:

In [25]: Test.__dict__
Out[25]:
dict_proxy({'__doc__': None,
            '__init__': <function __main__.__init__>,
            '__module__': '__main__',
            '__slots__': ['age'],
            'age': <member 'age' of 'Test' objects>,
            'fly': True})


In [36]: p.__dict__
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-36-3a1cec47d020> in <module>()
----> 1 p.__dict__

AttributeError: 'Test' object has no attribute '__dict__'

In [37]: p.age
Out[37]: 3

In [38]: p.fly
Out[38]: True

可以看到,__slots__方法并没有阻止由下至上的属性查找方法,只是不会再允许没有包含在__slots__数组中的属性再被赋值给实例了。但这并不妨碍,继续调用允许访问的属性,以及类属性。

 

关于__get__, __set__, __del__:

在前面的文章里面我也介绍过这三个魔法方法,虽然一般是用不到的,但是在写库的时候它们有特别的用途。他们是python另外一个协议descriptor的根基。

同一个对象的不同属性之间可能存在依赖关系。当某个属性被修改时,我们希望依赖于该属性的其他属性也同时变化。在这种环境下面__dict__方法就无法办到。因为__dict__方法只能用来存储静态属性。python提供了多种即时生成属性的方法。其中一种就是property。property是特殊的属性。比如我们为上面的例子增加一个property特性,使得他能够动态变化。来看这个例子:

class Test(object):
    fly = True

    def __init__(self, age):
        self.age = age

    def whether_fly(self):
        if self.age <= 30:
            return True
        else:
            return False

    def just_try_try(self, other):
        pass

    whether_fly = property(whether_fly)

p = Test(20)
print p.age
print p.whether_fly
p.age = 40
print p.age
print p.whether_fly

output:

20
True
40
False

可以看到 我们可以使用这种手段,动态修改属性值。property有四个参数。前三个参数为函数,分别用于处理查询特性、修改特性、删除特性。最后一个参数为特性的文档,可以为一个字符串,起说明作用。这里我只是要到了第一个参数,查询的时候动态修改他的返回值,而第二个参数是在修改值的时候就会体现出来。

 

Reference:

http://www.cnblogs.com/vamei/archive/2012/12/11/2772448.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值