魔术方法(属性访问控制):
### `__getattr__`魔术方法:
在访问一个对象的某个属性的时候,如果这个属性不存在,那么就会执行这个方法。
### `__setattr__`魔术方法:
给一个对象设置属性的时候,就会执行这个魔术方法。要注意的是,使用`self.__dict__[key]=value`的形式,避免产生死循环的递归。
### `__getattribute__`魔术方法:
在访问一个对象的属性的时候,都会执行这个魔术方法。要注意的是,使用`super(类名,self).__getattribute__(item)`来避免产生死循环的递归。
### `__getattr__`与`__getattribute__`区别:
1. `__getattr__`只有属性不存在的时候才会调用。
2. `__getattribute__`不管属性存不存在都会调用。
#encoding: utf-8
import logging
class Person(object):
def __init__(self,name):
# 0.1 pname
# 0.2 pname可以使用,但是会警告,在这个版本以后推荐使用name属性
# 0.3 pname不能再使用
self.name = name
self.age = 0
self.is_adult = False
def __getattr__(self, item):
# item:属性的名字
if item == 'pname':
logging.warning('pname属性已经被废弃,在下一个版本中不再使用这个属性,推荐使用name属性')
return self.name
else:
raise AttributeError(item+'属性不存在')
def __setattr__(self, key, value):
# key:属性的名字
# value:属性的值
# print('key:',key)
# print('value:',value)
# self.__dict__[key] = value
if key == 'age':
self.__dict__['age'] = value
if value >= 18:
self.__dict__['is_adult'] = True
else:
self.__dict__['is_adult'] = False
else:
self.__dict__[key] = value
def __getattribute__(self, item):
print('='*30)
print(item)
return super(Person, self).__getattribute__(item)
p1 = Person('zhiliao')
# print(p1.name)
# print(p1.name)
# p1.age = 17
# print(p1.is_adult)
print(p1.name)
print(p1.abc)
# exe_count = 0
# def greet():
# print('hello')
# global exe_count
# if exe_count < 10:
# exe_count += 1
# greet()
#
# greet()