1. 设置属性发送了什么?
class A(object):
def __init__(self):
self.a = 1
obj = A()
print(obj.a)
obj.b = 2
print(obj.b)
'''
self.属性=值 会触发 __setattr__方法
自定义类 A没有定义这个方法, 会调用父类的object的__setattr__的方法
class object:
...
def __setattr__(self, *args, **kwargs): # real signature unknown 真实签名未知
""" Implement setattr(self, name, value). """
pass
_________________C语言写的看不到源码_____________________
'''
2. 自定义setattr方法递归错误
一般情况下, 创建对象, 不会自己写__setattr__方法. 下面为演示代码不要纠结...
class A(object):
def __setattr__(self, key, value):
self.key = value
obj = A()
obj.a = 1
print(obj.a)
运行上面这个程序会提示报错
RecursionError: maximum recursion depth exceeded 递归错误:超过最大递归深度
每次在遇到 self.属性=值 时候会触发setattr,
在setattr中有 self.属性=值 再次触发setattr, 这就造成了无限循环, 最终报错.
![2022-10-22_00867](https://img-blog.csdnimg.cn/img_convert/2337f1c293bfc6d9ae7467c90e8c1d42.png)
3. 解决问题
在setattr中有 self.属性=值 会自己触发自己, 只要避免自己调用自己就可以解决问题.
在setattr中不要出现 self.属性=值, 又能设置值即可.
3.1 方式1 父类中更新子类的值
使用object的setattr方法, 在父类中更新子类的值.
class A(object):
def __setattr__(self, key, value):
object.__setattr__(self, key, value)
obj = A()
obj.a = 1
print(obj.a)
3.2 方法2 以字典形式修改值
class A(object):
def __setattr__(self, key, value):
"""
对象.__dict__可以将对象的所有属性以字典的形式展示,
支持self.__dict__[key] = value 添加修改值
"""
self.__dict__[key] = value
obj = A()
obj.a = 1
print(obj.a)
obj.__dict__['b'] = 2
print(obj.__dict__)
4. 字典使用.属性
Python中的字典, 使没有办法通过字典.key取到value值的.
Python中一切都是对象, 字典也是对象,
之所有字典.key会报错则是没有在创建字典对象的类中写__setattr__与__getattr__方法.
class MyDict(dict):
def __setattr__(self, key, value):
object.__setattr__(self, key, value)
def __getattr__(self, item):
return self.item
dic = MyDict()
print(dic)
dic['name'] = 'kid'
dic.age = 18
print(dic)
print(dic.age)
终端显示:
{}
{'name': 'kid'}
18
_______________________________________
现在字典是可以使用点, 但是值不在同一空间中.
字典使用[]会触发dict.__setitem__方法, 那么再__setattr__使用dict.__setitem__即可.
class MyDict(dict):
def __setattr__(self, key, value):
dict.__setitem__(self, key, value)
def __getattr__(self, item):
return self.get(item)
dic = MyDict()
print(dic)
dic['name'] = 'kid'
dic.age = 18
print(dic)
print(dic.name, dic.age)
终端显示:
{}
{'name': 'kid', 'age': 18}
kid 18