# class Cat: # class_level = '贵族' # def __init__(self, name, type, speed, age): # self.name = name # self.type = type # self.speed = speed # self.age = age # # def run(self): # print('%s岁的%s%s正在以%s的速度奔跑' % (self.age, self.type, self.name, self.speed)) # # def __getattr__(self, item): # print('你找的%s属性不存在' % item) # # def __setattr__(self, key, value): # print('你在设置属性') # # def __delattr__(self, item): # print('你在删除属性') # xiaohua = Cat('小花', '橘猫', '10m/s', 5) # 你在设置属性 # 你在设置属性 # 你在设置属性 # 你在设置属性 # xiaohua.run() # 你找的属性不存在 # 你找的属性不存在 # 你找的属性不存在 # 你找的属性不存在 # None岁的NoneNone正在以None的速度奔跑 # 可以看到__setattr__和__getattr__被触发了,为什么呢?我们上面的代码只是做了一个实例化和调用一个方法;实例化就是要找到__init__函数设置实例的数据属性, # 所以这里__setattr__被触发了,但是__getattr__为什么被触发了呢?因为我们的__setattr__函数下面只是打印了一行,并没有任何的其它赋值操作,所以__init__里面的数据属性 # 没有被赋值,在对象调用run方法的时候就找不到self.age,self.type,self.name,self.speed这些属性,所以就会触发__getattr__方法 ''' 下面总结这3个方法的使用场景: __setattr__添加/修改属性会触发它的执行 __getattr__只有在使用点调用属性且属性不存在的时候才会触发 __delattr__删除属性的时候会触发 类调用无效 ''' # 如果我们在Class没有定义这3个方法,那么系统会用Python自带的内部函数,如果我们在类里面字定义了这3个函数,那么python会先调用我们自定义的这3个函数 # 上面的__getattr__之所以被触发就是因为__setattr__函数下面只是打印了一行,并没有任何的其它赋值操作 class Cat: class_level = '贵族' def __init__(self, name, type, speed, age): self.name = name self.type = type self.speed = speed self.age = age def run(self): print('%s岁的%s%s正在以%s的速度奔跑' % (self.age, self.type, self.name, self.speed)) def __getattr__(self, item): print('你找的%s属性不存在' % item) def __setattr__(self, key, value): print('你在设置属性') # self.key = value # 这种方法不行,会产生无限递归了,因为他本身self.key=value也会触发__setattr__ self.__dict__[key] = value # 我们在给对象属性赋值的时候,内部原理就是操作对象的__dict__字典,所以我们可以直接操作对象的字典实现属性赋值 def __delattr__(self, item): print('你在删除属性') # del self.item # 无限递归了,和上面的__setattr__原理一样 self.__dict__.pop(item) xiaohua = Cat('小花花', '波斯猫', '10m/s', 8) # 触发__setattr__方法 # 你在设置属性 # 你在设置属性 # 你在设置属性 # 你在设置属性 xiaohua.run() # 8岁的波斯猫小花花正在以10m/s的速度奔跑 xiaohua.weight = '5KG' # 触发__setattr__方法 # 你在设置属性 print(xiaohua.__dict__) # {'name': '小花花', 'type': '波斯猫', 'speed': '10m/s', 'age': 8, 'weight': '5KG'} del xiaohua.weight # 触发__delattr__方法 # 你在删除属性 print(xiaohua.__dict__) # {'name': '小花花', 'type': '波斯猫', 'speed': '10m/s', 'age': 8} xiaohua.abc # 触发__getattr__方法 # 你找的属性不存在 # class Foo: # pass # # print(dir(Foo)) # dir()可以看到类的更多内置方法