下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922
论坛 >编程语言 >Python 中的属性访问

Python 中的属性访问

spring发布于 2017-10-18 10:36查看:646回复:1

        在Python中,对于一个对象的属性访问,我们一般采用的是点(.)属性运算符进行操作。例如,有一个类实例对象foo,它有一个name属性,那便可以使用foo.name对此属性进行访问。一般而言,点(.)属性运算符比较直观,也是我们经常碰到的一种属性访问方式。然而,在点(.)属性运算符的背后却是别有洞天,值得我们对对象的属性访问进行探讨。

        在进行对象属性访问的分析之前,我们需要先了解一下对象怎么表示其属性。为了便于说明,本文以新式类为例。有关新式类和旧式类的区别,大家可以查看Python官方文档。


     对象的属性

        Python中,“一切皆对象”。我们可以给对象设置各种属性。先来看一个简单的例子:

image.png

        上面的例子中,我们定义了两个类。类Animal定义了一个属性run;类Dog继承自Animal,定义了一个属性fly和两个函数。接下来,我们实例化一个对象。对象的属性可以从特殊属性__dict__中查看。

image.png

        由上面的例子可以看出:属性在哪个对象上定义,便会出现在哪个对象的__dict__中。例如:

      类Animal定义了一个属性run,那这个run属性便只会出现在类Animal__dict__中,而不会出现在其子类中。

      类Dog定义了一个属性fly和两个函数,那这些属性和方法便会出现在类Dog__dict__中,同时它们也不会出现在实例的__dict__中。

      实例对象dog__dict__中只出现了一个属性age,这是在初始化实例对象的时候添加的,它没有父类的属性和方法。

      由此可知:Python中对象的属性具有 “层次性”,属性在哪个对象上定义,便会出现在哪个对象的__dict__中。

        在这里我们首先了解的是属性值会存储在对象的__dict__中,查找也会在对象的__dict__中进行查找的。至于Python对象进行属性访问时,会按照怎样的规则来查找属性值呢?这个问题在后文中进行讨论。



     对象属性访问与特殊方法__getattribute__

        正如前面所述,Python的属性访问方式很直观,使用点属性运算符。在新式类中,对对象属性的访问,都会调用特殊方法__getattribute____getattribute__允许我们在访问对象属性时自定义访问行为,但是使用它特别要小心无限递归的问题。

        还是以上面的情景为例:

image.png

        上面的例子中我们重写了__getattribute__方法。注意我们使用了super()方法来避免无限循环问题。下面我们实例化一个对象来说明访问对象属性时__getattribute__的特性。

image.png

        由上面的验证可知,__getattribute__是实例对象查找属性或方法的入口。实例对象访问属性或方法时都需要调用到__getattribute__,之后才会根据一定的规则在各个__dict__中查找相应的属性值或方法对象,若没有找到则会调用__getattr__(后面会介绍到)。__getattribute__是Python中的一个内置方法,关于其底层实现可以查看相关官方文档,后面将要介绍的属性访问规则就是依赖于__getattribute__的。


     对象属性控制

        在继续介绍后面相关内容之前,让我们先来了解一下Python中和对象属性控制相关的相关方法。

        __getattr__(self, name)__getattr__可以用来在当用户试图访问一个根本不存在(或者暂时不存在)的属性时,来定义类的行为。前面讲到过,当__getattribute__方法找不到属性时,最终会调用__getattr__方法。它可以用于捕捉错误的以及灵活地处理AttributeError。只有当试图访问不存在的属性时它才会被调用。

        __setattr__(self, name, value)__setattr__方法允许你自定义某个属性的赋值行为,不管这个属性存在与否,都可以对任意属性的任何变化都定义自己的规则。关于__setattr__有两点需要说明:第一,使用它时必须小心,不能写成类似self.name = “Tom”这样的形式,因为这样的赋值语句会调用__setattr__方法,这样会让其陷入无限递归;第二,你必须区分 对象属性 和 类属性 这两个概念。后面的例子中会对此进行解释。

        __delattr__(self, name)__delattr__用于处理删除属性时的行为。和__setattr__方法要注意无限递归的问题,重写该方法时不要有类似del self.name的写法。

        还是以上面的例子进行说明,不过在这里我们要重写三个属性控制方法。

image.png

        以下进行验证。首先是__getattr__:

image.png

        可以看到,属性访问时,当访问一个不存在的属性时触发__getattr__,它会对访问行为进行控制。接下来是__setattr__

image.png

        实例对象的__setattr__方法可以定义属性的赋值行为,不管属性是否存在。当属性存在时,它会改变其值;当属性不存在时,它会添加一个对象属性信息到对象的__dict__中,然而这并不改变类的属性。从上面的例子可以看出来。

        最后,看一下__delattr__

image.png

收藏(0)0
查看评分情况

全部评分

此主贴暂时没有点赞评分

总计:0

回复分享

版主推荐

    共有1条评论

    • 课课家运营团队
    • 酸酸~甜甜
    • Mr ken
    • YUI
    • cappuccino
    • mr jack
    • IT宅男
    • Mright
    • 课课家技术团队1
    • 选择版块:

    • 标题:

    • 内容

    • 验证码:

    • 标题:

    • 内容

    • 选择版块:

    移动帖子x

    移动到: