class类: 属性访问,特性和修饰符

  1. 属性的基本操作:

    默认情况下,创建任何类内部的属性都将支持以下4种操作:

  • 创建新属性,

  • 为已有的属性赋值,

  • 获取属性的值,

  • 删除属性。


    特性是一个函数,看起来(在语法上)就是一个简单的属性。但是这个函数可以被调用,而不仅仅是用于存储的对象引用。除了复杂程度,特性和属性的另一个区别在于,我们不能轻易地为已有对象添加新特征。

    可以用两种方式来创建特征。我们可以使用@property修饰符或者使用property()函数。特征的两个基本设计模式:1.主动计算(Eager Calculation):每当更新特征值时,其他相关特性值都会立即被重新计算。2.延迟计算(Lazy Calculation):仅当访问特性时,才会触发计算过程。

    属性访问的3个标准函数:__getattr__(),__setattr__()和__delattr__(),此外,还可以用__dir__()函数来查看属性的名称:

  1.     __setattr__()函数用于属性的创建和赋值

  2.     __getattr__()函数可以用来做两件事。首先,如果属性已经被赋值,则不会被调用,直接返回属性值即可。其次,如果属性没有被赋值,那么将调用此函数的返回值。如果找不到相关属性,要记得抛出AttributeError异常。

  3.     __delattr__()函数用于删除属性。

  4.     __dir__()函数用于返回属性名称列表。

  5.     扩展类。通过重写__setattr__()和__delattr__()函数使得它几乎时不可变的。也可以使用__slots__替换内部的__dict__对象

  6. 封装类。提供对象(或对象集合)属性访问的代理实现。这可能需要完全重写和属性相关的那3个函数

  7. 创建类并提供和特性功能一样的函数。使用这些方法来对特征逻辑集中处理。

  8. 创建延迟计算属性,仅当需要时才触发计算过程。对于一些属性,它的值可能来自文件,数据库或网络。这是__getattr__()函数的常见方法

  9. 创建主动计算属性,其他属性更新时会相应地更新主动计算属性的值,这是通过重写__setattr__()函数实现。

    

    __slots__={'rank','suit','hard','soft'}#类中添加这个属性,把这设为唯一被允许操作的属性。这会使得对象内部的__dict__对象不再有效并阻止对其他属性的访问。如果需要,也可以向如下代码绕过不可变对象。

object.__setattr__(c,'bad',5).

    __slots__的主要目的时通过限制属性的数量来节约内存。

    可使用tuple子类创建不可变对象

    ps:我们不能轻易地在类的内部对属性赋值

__getattribute__()方法提供了对属性更底层的一些操作。默认的实现逻辑是先从内部的__dict__或__slots__中查找已有的属性。如果属性没有找到则调用__getattr__()函数。如果值是一个修饰符,对修饰符进行处理。否则,返回当前值即可。通过重写这个方法,可以达到以下目的:

  • 可以有效阻止属性访问。在这个方法中,抛出异常而非返回值。相比于在代码中仅仅使用下划线(_)为开头把一个名字标记为私有的方式,这种方式是的属性的封装更透彻。

  • 可以仿照__getattr__()函数的工作方式来创建新属性。在这种情况下,可以绕过__getattribute__()的实现逻辑

  • 可以是的属性执行单独或不同的任务。但这样会降低程序的可读性和可维护性,这是个很糟糕的想法

  • 可以改变修饰符的行为。虽然技术上可行,改变修饰符的行为却是个糟糕的想法。

    ps:当实现__getattribute__()方法时,将阻止任何内部属性访问函数体,这一点很重要,如果试图获取self.name的值,会导致无限递归。

为了获得__getattribute__()方法中的属性值,必须显式调用object基类中的方法,eg:object.__getattribute__(self,name)

一般情况下,不会轻易使用__getattribute__().该函数的默认实现非常复杂,不多数情况下,使用特征或改变__getattr__()函数的行为就足以满足需求了。

评论
热度 ( 1 )

© foreveryoung2014 | Powered by LOFTER