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) #同样的道理,这里必须执行,才能真正的设置成功
    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.xgetattribute999>>>

此外,__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

时间: 2024-10-10 01:47:41

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

python类与对象各个魔法方法总结

1.python类与对象各个魔法方法总结: 2.各个魔法方法应用举例: 3.实例训练: (1)我们都知道在 Python 中,两个字符串相加会自动拼接字符串,但遗憾的是两个字符串相减却抛出异常.因此,现在我们要求定义一个 Nstr 类,支持字符串的相减操作:A – B,从 A 中去除所有 B 的子字符串. class Nstr(str): def __sub__(self,other):  self=list(self)         other=list(other) for i in ot

[python] 类常用的内置方法

内置方法 说明 __init__(self,...) 初始化对象,在创建新对象时调用 __del__(self) 释放对象,在对象被删除之前调用 __new__(cls,*args,**kwd) 实例的生成操作 __str__(self) 在使用print语句时被调用 __getitem__(self,key) 获取序列的索引key对应的值,等价于seq[key] __len__(self) 在调用内联函数len()时被调用 __cmp__(stc,dst) 比较两个对象src和dst __ge

JavaSE8基础 不同包下,没有关系的类可以访问到 公有方法

os :windows7 x64    jdk:jdk-8u131-windows-x64    ide:Eclipse Oxygen Release (4.7.0)        代码一: package NOTjizuiku; import jizuiku.Person; public class Demo{ public static void main(String[] agrs) { Person p = new Person(); //不同包下,没有关系的类可以访问到 公有方法 p.

Python类属性和类方法

01. 类的结构 1.1 术语 —— 实例 使用面相对象开发,第 1 步 是设计 类 使用 类名() 创建对象,创建对象 的动作有两步: 1) 在内存中为对象 分配空间 2) 调用初始化方法 __init__ 为 对象初始化 对象创建后,内存 中就有了一个对象的 实实在在 的存在 —— 实例 因此,通常也会把: 创建出来的 对象 叫做 类 的 实例 创建对象的 动作 叫做 实例化 对象的属性 叫做 实例属性 对象调用的方法 叫做 实例方法 在程序执行时: 对象各自拥有自己的 实例属性 调用对象方

Python 类属性与实例属性的关联

类属性是属于一个类的变量,就像是C++中类的静态成员变量,你只需将该属性定义在所有方法的作用域外,即为类属性,但一般是紧跟在类名后面,类属性为所有实例所共有,你可以通过 类名.属性 来调用类属性 >>> class A:       count = 0; #这就是类属性       def __init__(self):           A.count += 1  #每次调用该方法 count 自增 1       def output(self):           print(

python 类属性 实例属性 类方法 实例方法 静态方法(转载)

本文是转载,纯粹是为了方便后面自己查看,建议还是看原文的:http://www.cnblogs.com/dolphin0520/archive/2013/03/29/2986924.html 一.先来谈一下类属性和实例属性 在前面的例子中我们接触到的就是类属性,顾名思义,类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似.对于公有的类属性,在类外可以通过类对象和实例对象访问. class people: name = 'j

Python私有属性set 和get方法

class Person(object): #self不是关键字,换成其他的标识符也是可以的,但是一般不要改 def run(self): print("run") def eat(self,food): print("eat" + food) def say(self): print("hello! my name is %s,i am %d years old" %(self.name,self.age)) def __init__(self

python 类属性、静态方法与类方法

1. 类属性 1.1 定义 在类中方法外通过属性名 = 属性值定义的属性 访问方式: 类名.属性名 对象名.属性名 class Student: cls_id = 102 stu = Student() print(Student.cls_id) print(stu.cls_id) print("---------") Student.cls_id = 103 print(Student.cls_id) print(stu.cls_id) print("---------&q

Python类属性详解

在python开发中,我们常常用到python的类,今天就通过实例和大家扒一扒类的属性,一起来看看吧. 类属性 1.类定义后就存在,而且不需要实例化 2.类属性使得相同类的不同实例共同持有相同变量 类属性实例 attrb.py class TestCss: cssa = 'class-attribe' def __init__(self): self.a = 0 self.b = 10 def info(self): print('a:',self.a,'b:',self.b,'cssa:',T