Python类属性访问的魔法方法:

1. __getattr__(self, name)
- 定义当用户试图获取一个不存在的属性时的行为

2. __getattribute__(self, name)
- 定义当该类的属性被访问时的行为

注意:当__getattr__与__getattribute__同时重写时,访问属性时,优先调用__getattribute__,只有当被访问的属性不存在时才触发__getattr__

3. __setattr__(self, name, value)
- 定义当一个属性被设置时的行为

4. __delattr__(self, name)
- 定义当一个属性被删除时的行为

>>> class C:
def __getattribute__(self, name):
print("getattribute")
return super().__getattribute__(name) #如果这里没有return语句,那么,c.x访问时__getattr__不会触发,因为相当于没有c.x这句话
def __getattr__(self, name):
print("getattr")
def __setattr__(self, name, value):
print("setattr")
super().__setattr__(name, value) #同样的道理,这里必须执行,才能真正的设置成功。这里为啥不能这么写:self.name = value?请看下面关于__setattr__死循环陷阱的说明
def __delattr__(self, name):
print("delattr")
#这里应该加一句 super().__delattr__(name),不然,删除指定对象是不会成功,看下面的执行结果就可以验证 >>> c = C()
>>> c.x
getattribute
getattr
>>> c.x = 999
setattr
>>> c.x
getattribute
999
>>> del c.x
delattr
#上面已经删除了c.x,但下面访问时,还是访问到了,说明删除没有成功,因为__delattr__中没有super().__delattr__(name)这句话
>>> c.x
getattribute
999
>>>

此外,__setattr__会有死循环陷阱:

>>> class Rect():
def __init__(self, width=0, height=0):
self.width = width
self.height = height
def __setattr__(self, name, value):
if name == 'square':
self.width = value
self.height = value
else:
self.name = value
def getArea(self):
return self.width * self.height >>> r = Rect(2,8)
Traceback (most recent call last):
File "<pyshell#144>", line 1, in <module>
r = Rect(2,8)
File "<pyshell#143>", line 3, in __init__
self.width = width
File "<pyshell#143>", line 10, in __setattr__
self.name = value
File "<pyshell#143>", line 10, in __setattr__
self.name = value
File "<pyshell#143>", line 10, in __setattr__
self.name = value
File "<pyshell#143>", line 10, in __setattr__
……

为什么会这样?

主要是在__init__内,给width与height赋值的时候,就会自动触发__setattr__方法,当参数2,8分别传入width与height的时候,初始化时,赋值触发__setattr__,因为2传给的是width属性,所以,不是suqare,就执行else的语句(self.name = value),然而,在else的语句又是一个赋值语句,又会自动触发__setattr__,所以,就会造成死循环。其解决方法有两种:

1.self.name = value这句修改成:super().__setattr__(name, value),使用父类的__setattr__来赋值(这为啥就不会死循环?别问我,反正Python的设计者解决了这个问题)

2.self.name = value这句修改成:self.__dict__[name] = value, 这样也是赋值,为啥不是死循环呢?哈哈,触发__setattr__的情况是访问访问对象的属性,而这里比较巧的是访问的是__dict__(对象的特殊属性,是用来存放当前对象所以的属性的字典)。

Python类属性访问的魔法方法的更多相关文章

  1. python 类属性与方法

    Python 类属性与方法 标签(空格分隔): Python Python的访问限制 Python支持面向对象,其对属性的权限控制通过属性名来实现,如果一个属性有双下划线开头(__),该属性就无法被外 ...

  2. 【python学习笔记】9.魔法方法、属性和迭代器

    [python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...

  3. python类属性和对象属性、类的普通方法和静态方法

    类属性和对象属性的定义 class LearnClass(): #类属性 cls_attr = None def __init__(self,arg): #对象属性 self.obj_attr = a ...

  4. 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘

    孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...

  5. python类属性 静态方法

      实例 实例就是由对象创建出来的实实在在的存在 创建出来的对象叫做类的实例 创建对象的动作叫做实例化 对象的属性叫做实例的属性 对象调用的方法叫做实例方法   类是一个特殊的对象   类属性 类属性 ...

  6. python学习笔记之七:魔法方法,属性

    在python中,有的名称会在前面和后面加上两个下划线,由这些名字组成的集合所包含的方法称为魔法方法(或者是特殊方法).如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下(确切地说是根据名 ...

  7. Python基础(二十一):面向对象“类”第四课——魔法方法

    先划一下重点: 6个魔法方法: 动态操作属性的4个函数: 魔法方法 魔法方法的简单介绍 魔法方法的命名规则:方法名(前后各有2个下划线). 通常情况下,不会主动去调用魔法方法,而是在满足一定的条件下, ...

  8. python基础第9章 魔法方法、属性和迭代器(一)

    __getitem__和__setitem__: 这个方法返回与指定键想关联的值.对序列来说,键应该是0~n-1的整数,其中n为序列的长度.对映射来说,键可以是任何类型. class A : __ge ...

  9. Python 类属性和方法

    import types class Dog(object): __slots__ = ("name", "color", "info") ...

随机推荐

  1. 怎么选择最适合自己的Linux培训机构?

    Linux培训已经成为入门Linux的一个重要途径,它的优势在于学习知识的系统性.快速性和实用性.Linux培训毕业的学员大多数拥有较强的实战动手能力,能够较快上手,更符合企业需求. 不过,大部分同学 ...

  2. zTree 模糊搜索

    /** * 搜索树,高亮显示并展示[模糊匹配搜索条件的节点s] * @param treeId * @param searchConditionId 搜索条件Id */ function search ...

  3. MIUI 的参与感

    最近这段时间在看小米联合创始人黎万强写的<参与感>这本书,看完我还挺有感触的.小米相信大家都一定有所耳闻. 2010 年 4 月 6 日            小米公司正式创立. 8 月 ...

  4. Gym - 101611D Decoding of Varints(阅读理解题 )

    Decoding of Varints ​ 题意&思路: 首先根据红色边框部分的公式算出x,再有绿色部分得知,如果x是偶数则直接除以2,x是奇数则(x+1)/-2. PS:这题有数据会爆掉un ...

  5. 2.git进阶篇总结

    阅读 Git 原理详解及实用指南 记录 进阶 1 - HEAD.master 与 branch: 介绍了 Git 中的一些「引用」:HEAD.master.branch.这里总结一下: HEAD 是指 ...

  6. VS单元测试"未能加载文件或程序集,或它的某一个依赖项"

    Autofac.Core.DependencyResolutionException : An error occurred during the activation of a particular ...

  7. C#学习笔记_08_面向对象

    08_面向对象 面向对象:一种看待问题解决问题的思维方式,着眼点在于找到一个能够帮助我们解决问题的实体,然后委托这个实体来帮我们解决问题:(在面向对象之前你要有一个女朋友,否则代码会经常出现bug) ...

  8. Python面向对象----继承, 重载

    1. 面向对象三大特性之继承. 继承的便捷是子类可以直接调用父类里面的方法和属性.(在强类型语言里面是只能调用公有成员), 不用重复的造轮子. 减少程序猿的负担.实现多态等上层结构 2. 父类代码 3 ...

  9. elisp 编程 if 特殊表

    elisp中的 if 特殊表与其他语言中的 if 语句逻辑上并无二致,关键在于如何使用. (if (> 4 3) (message "4 is greater than 3" ...

  10. PAT 1094. The Largest Generation (层级遍历)

    A family hierarchy is usually presented by a pedigree tree where all the nodes on the same level bel ...