类实例属性的设置与访问

Python 作为动态编程语言,可以在任意时刻为一个类实例设置属性,如果不加限制,则可以为一个实例属性设置任意类型的值。但有时我们可能希望对一个新的实例属性的值进行一些自定义的限制或更改,此时就可从 Python 的类定义层面进行考虑了。
其实细细追究下来,Python 中对一个类实例的属性就行访问和设置主要是跟下面 3 个特殊方法有关:
1、__getattr__(self, name):当访问的实例属性不存在于当前类实例的属性字典中时,该方法就会被调用。
2、__getattribute__(self, name):当访问实例属性时,该方法就会被调用,当没有这样的属性时,就会抛出 AttributeError,此时就会调用 __getattr__ 方法。为了避免无穷递归,应该总是调用其父类的 __getattribute__ 方法来获取此属性。
3、__setattr__(self, name, value):当设置实例属性时,该方法就会被调用。为了避免无穷递归,应该总是调用其父类的 __setattr__ 方法来设置此属性。
注意,如果在继承时这几个方法没有被子类覆盖,那么依然会影响到子类。
下面这个例子演示了如何访问一个类实例,以及将新实例属性的值限制为整数。

>>> class T:
def __init__(self, obj):
self.obj = obj # 这里也会调用 __setattr__ 方法
def __getattr__(self, name):
try:
return self.obj[name] # 以 obj 中的值来代替
except KeyError:
raise AttributeError("'T' object has no attribute '%s'" %name)
def __getattribute__(self, name):
return super().__getattribute__(name) # 避免无穷递归
def __setattr__(self, name, value):
print('setting attribute', name)
if name != 'obj' and not isinstance(value, int): # “obj”属性不是整数,需要排除
raise TypeError("value need to be an integer.")
super().__setattr__(name, value) # 避免无穷递归

运行结果:

>>> t = T({'key': 'vvv', 'aa': 'b'})
setting attribute obj
>>>
>>> t.__dict__
{'obj': {'key': 'vvv', 'aa': 'b'}}
>>> t.a # 这里因为属性“a”也不在属性“obj”中
Traceback (most recent call last):
File "<pyshell#132>", line 6, in __getattr__
return self.obj[name]
KeyError: 'a'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "<pyshell#135>", line 1, in <module>
t.a
File "<pyshell#132>", line 8, in __getattr__
raise AttributeError("'T' object has no attribute '%s'" %name)
AttributeError: 'T' object has no attribute 'a'
>>> t.aa # aa 在 obj 中
'b'
>>> t.x = 'aaa'
setting attribute x
Traceback (most recent call last):
File "<pyshell#57>", line 1, in <module>
t.x = 'aaa'
File "<pyshell#42>", line 11, in __setattr__
raise TypeError("value need to be an integer.")
TypeError: value need to be an integer.
>>>
>>> t.x = 13
setting attribute x
>>>
>>> t.__dict__
{'obj': {'key': 'vvv', 'aa': 'b'}, 'x': 13}
>>>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值