内容简介:Python对象属性的那些事
__dict__属性
在没使用 __slots__
的情况下, __new__
会为每个实例创建一个 __dict__
字典,来保存实例的所有属性。在进行属性寻找的时候,会先在对象的 __dict__
中找,找不到,就去类的 __dict__
中找,再找不到就去父类的 __dict__
中找,。。
__slots__属性
类是创建对象的模版。在静态类型语言中,对象只能拥有类中定义的那些属性。而在 Python 中,可以在运行时,随意的增加或删除对象的属性。这就很可能造成:运行时,为对象增加了很多属性,占用了很多的内存。为了避免类似的现象,
Python的新式类提供了 __slots__
类属性,用来限制类的对象所能拥有的属性
。
# coding: utf8 class NonSlots(object): pass class Slots(object): # 一定要是新式类 __slots__ = ("a", "b") # 属性名列表 if __name__ == "__main__": non_slots = NonSlots() non_slots.c = "c" slots = Slots() slots.a = "a" # 因为a在__slots__中,所以不会出异常 slots.c = "c" # 此处会出AttributeError
默认情况下, __new__
会为每一个实例创建一个属性字典 __dict__
,用来保存实例的所有属性。但是当使用 __slots__
时, __new__
不会为实例创建该字典。
当父类没有 __slots__
时,子类仍然有 __dict__
, __slots__
之外的属性,会被保存到属性字典中。此时, __slots__
的意义,也就不大了。
当父类也有 __slots__
时,子类的 __slots__
的值,可以看成是自己的 __slots__
加上 父类的 __slots__
。
描述符
有三个方法:
-
__get__(self, obj, objtype=None) --> value
-
__set__(self, obj, value) --> None
-
__delete__(self, obj) --> None
重写了其中一个或多个方法的对象,就是描述符。
注意:
- 描述符必须是新式类的对象
-
描述符是在
object.__getattribute__
方法中,被调用的。重写__getattribute__
方法,可能会阻止描述符的自动调用 -
描述符必须是 类属性
(因此,描述符是被类的所有实例所共享的)。当使用 该类的实例
访问描述符时,会自动调用
__get__
方法;设置描述符时,会自动调用__set__
方法;删除描述符时,会自动调用__delete__
方法
Python中的很多高级特性,都是通过描述符实现的。比如,staticmethod、classmethod等。
下面看一个自己实现classmethod的例子:
[root@iZj6chejzrsqpclb7miryaZ ~]# cat test.py # coding: utf8 from functools import partial class MyClassMethodDescriptor(object): def __init__(self, func): self._func = func def __get__(self, obj, objtype): # obj:访问描述符的实例 # objtype:等价于 type(obj) print "{obj: %r, objtype: %r}" % (obj, objtype) return partial(self._func, objtype) def __set__(self, obj, val): # obj:设置描述符的实例 # val:要设置成的值 pass def __del__(self, obj): # obj:删除描述符的实例 pass def func(cls): print "cls is: %r" % cls print "func() is invoked..." class Test(object): my_classmethod = MyClassMethodDescriptor(func) test = Test() test.my_classmethod() [root@iZj6chejzrsqpclb7miryaZ ~]# python test.py {obj: <__main__.Test object at 0x7fe9b99c54d0>, objtype: <class __main__="" test=""> } cls is: <class __main__="" test=""> func() is invoked... </class> </class>
与属性相关的魔术方法
属性访问
-
__getattribute__(self, attr_name)
它是 新式类 的一个魔术方法,访问对象的任意属性时,都会先调用这个方法。如果这个方法,抛出AttributeError,则调用对象的__getattr__(self, attr_name)
方法 -
__getattr__(self, attr_name)
当对象没有名为attr_name
的属性时,就会调用它的__getattr__(self, attr_name)
方法
当使用内建函数getattr(obj, attr_name, ...)获取obj的属性时:
-
如果是新式类,则先调用
__getattribute__
方法,如果出AttributeError,则调用__getattr__
方法 -
如果是经典类, 在找不到该属性的情况下
,会调用
__getattr__
方法
需要注意的是:
在 __getattribute__
和 __getattr__
方法中,调用 getattr(self, xxx)
可能会造成死递归。一个解决方案是使用 object.__getattribute__(self, attr_name)
(新式类)。
设置属性
-
__setattr__(self, name, value)
当设置对象的属性时,会调用这个魔术方法。
当使用内建函数setattr(obj, name, value)设置对象的属性时,会调用 __setattr__
方法。所以在 __setattr__
方法中,调用 setattr(self, ...)
可能造成死递归。一个解决方案是使用属性字典 __dict__
。比如:
[root@iZj6chejzrsqpclb7miryaZ ~]# cat test.py class Test: def __setattr__(self, name, value): print "__setattr__" self.__dict__[name] = value def __getattr__(self, name): print "__getattr__" raise AttributeError("has no attribute: %s" % name) test = Test() test.a = "a" print test.a [root@iZj6chejzrsqpclb7miryaZ ~]# python test.py __setattr__ a
删除属性
__delattr__
方法 和 delattr内建函数:
[root@iZj6chejzrsqpclb7miryaZ ~]# cat test.py class Test: def __setattr__(self, name, value): print "__setattr__" self.__dict__[name] = value def __getattr__(self, name): print "__getattr__" raise AttributeError("has no attribute: %s" % name) def __delattr__(self, name): print "__delattr__" self.__dict__.pop(name) test = Test() test.a = "a" print test.a delattr(test, "a") print getattr(test, "a", None) [root@iZj6chejzrsqpclb7miryaZ ~]# python test.py __setattr__ a __delattr__ __getattr__ None
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- JavaScript对象之数据属性与访问器属性
- python – Django属性错误. ‘module’对象没有属性’rindex’
- JavaScript之对象属性
- [译] 深入 JS 对象属性
- 什么是面向对象-类的属性
- 数组对象根据对象中指定的属性去重?你知道多少
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法分析导论(第2版)(英文版)
[美]Robert Sedgewick(罗伯特•塞奇威克)、[美]Philippe Flajolet(菲利普•弗拉若莱) / 电子工业出版社 / 2015-6 / 128.00元
《算法分析导论(第2版)(英文版)》全面介绍了算法的数学分析中所涉及的主要技术。涵盖的内容来自经典的数学课题(包括离散数学、初等实分析、组合数学),以及经典的计算机科学课题(包括算法和数据结构)。《算法分析导论(第2版)(英文版)》的重点是“平均情况”或“概率性”分析,书中也论述了“最差情况”或“复杂性”分析所需的基本数学工具。 《算法分析导论(第2版)(英文版)》第 1 版为行业内的经典著......一起来看看 《算法分析导论(第2版)(英文版)》 这本书的介绍吧!