Python类属性访问的魔法方法
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类属性访问的魔法方法的更多相关文章
- python 类属性与方法
Python 类属性与方法 标签(空格分隔): Python Python的访问限制 Python支持面向对象,其对属性的权限控制通过属性名来实现,如果一个属性有双下划线开头(__),该属性就无法被外 ...
- 【python学习笔记】9.魔法方法、属性和迭代器
[python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...
- python类属性和对象属性、类的普通方法和静态方法
类属性和对象属性的定义 class LearnClass(): #类属性 cls_attr = None def __init__(self,arg): #对象属性 self.obj_attr = a ...
- 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘
孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...
- python类属性 静态方法
实例 实例就是由对象创建出来的实实在在的存在 创建出来的对象叫做类的实例 创建对象的动作叫做实例化 对象的属性叫做实例的属性 对象调用的方法叫做实例方法 类是一个特殊的对象 类属性 类属性 ...
- python学习笔记之七:魔法方法,属性
在python中,有的名称会在前面和后面加上两个下划线,由这些名字组成的集合所包含的方法称为魔法方法(或者是特殊方法).如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下(确切地说是根据名 ...
- Python基础(二十一):面向对象“类”第四课——魔法方法
先划一下重点: 6个魔法方法: 动态操作属性的4个函数: 魔法方法 魔法方法的简单介绍 魔法方法的命名规则:方法名(前后各有2个下划线). 通常情况下,不会主动去调用魔法方法,而是在满足一定的条件下, ...
- python基础第9章 魔法方法、属性和迭代器(一)
__getitem__和__setitem__: 这个方法返回与指定键想关联的值.对序列来说,键应该是0~n-1的整数,其中n为序列的长度.对映射来说,键可以是任何类型. class A : __ge ...
- Python 类属性和方法
import types class Dog(object): __slots__ = ("name", "color", "info") ...
随机推荐
- CStatic设置位图
CStatic 用于显示位图 如果要显示图标,则必须要设置窗口属性为 SS_BITMAP 和 SS_CENTERIMAGE,实例代码如下: //获得指向静态控件的指针 CStatic *pStatic ...
- Web 常用
System.Web.Hosting.HostingEnvironment.MapPath(); HttpUtility.UrlEncode();
- Free中的buffer和cache理解
吐血推荐文章: Linux内存中的Cache真的能被回收么? free中的buffer和cache: redhat对free输出的解读 两者都是RAM中的数据.简单来说,buffer是即将要被写入磁盘 ...
- js可以随意拖拽的div的实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 数据结构与算法(6) -- heap
binary heap就是一种complete binary tree(完全二叉树).也就是说,整棵binary tree除了最底层的叶节点之外,都是满的.而最底层的叶节点由左至右又不得有空隙. 以上 ...
- golang实现高阶函数之filter
package main import "fmt" type student struct{ name string grade int8 } func filter(stu [] ...
- ssm 数据库连接池配置
1.工程引入druid-1.1.2.jar包2.修改spring-common.xml文件 <!-- 1. 数据源 : DruidDataSource--> <bean id=&qu ...
- hdu2010 水仙花数【C++】
水仙花数 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- scp相关命令总结
scp 跨机远程拷贝scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.当你服务器硬盘 ...
- 像 IDE 一样使用 vim
本文转载自:https://github.com/yangyangwithgnu/use_vim_as_ide ##[目录] 0 vim 必知会........0.1 .vimrc 文件....... ...