Python对象属性的那些事

栏目: Python · 发布时间: 6年前

内容简介: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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Apache Modules Book

The Apache Modules Book

Nick Kew / Prentice Hall PTR / 2007-02-05 / USD 54.99

"Do you learn best by example and experimentation? This book is ideal. Have your favorite editor and compiler ready-you'll encounter example code you'll want to try right away. You've picked the right......一起来看看 《The Apache Modules Book》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码