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. Android组件化最佳实践 ARetrofit原理

    ARetrofit原理讲原理之前,我想先说说为什么要ARetrofit.开发ARetrofit这个项目的思路来源其实是Retrofit,Retrofit是Square公司开发的一款针对Android网 ...

  2. DOCKER - POD操作

    强制删除 Terminating 的pod kubectl delete  -n <namespace> <pod podname> --grace-period=0 --fo ...

  3. iOS 中plist文件中配置key值冲突的现象

    iOS开发一些特殊的软件需要在项目中配置对应的key值,然而近期在项目中发现一个有意思的现象,苹果官方文档中提供的key值很多,但其实有一些彼此可能有冲突,当你同时配置了彼此冲突的key值,可能会出现 ...

  4. uva 1587(Box UVA - 1587)

    题目大意是给定6个数对,每个数对代表一个面的长和宽,判断这6个面是否能构成一个长方体. 这种题一看很复杂,但是只要不想多了实际上这就是一个水题... 首先说明一下判断的思路: 1.长方体是有三个对面的 ...

  5. 如何反向遍历List集合

    List接口中提供了ListIterator<E> listIterator()这样的一个方法,可以获得一个ListIterator接口的实例,如下: 看一下他的方法: 了解了这些之后再看 ...

  6. java面试题(转)

    1.面向对象的特征有哪些方面?答:面向对象的特征主要有以下几个方面:- 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为,并不关注这些 ...

  7. 14.multi_match+most-fields策略

    主要知识点 most-fields策略的用法 most-fields策略和best-fields的比较         best-fields策略:将某一个field匹配尽可能多的关键词的doc优先返 ...

  8. cuda npp库旋转图片

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h&g ...

  9. Java基础学习总结(24)——Java单元测试之JUnit4详解

    Java单元测试之JUnit4详解 与JUnit3不同,JUnit4通过注解的方式来识别测试方法.目前支持的主要注解有: @BeforeClass 全局只会执行一次,而且是第一个运行 @Before  ...

  10. crontab定时任务安装、使用方法

    本文介绍下,在linux中安装crontab的方法,以及crontab的具体用法,有需要的朋友参考下. 这里使用yum方式安装crontab:  复制代码代码示例: [root@CentOS ~]# ...