getattr和getattribute魔法函数
-
__getattr__
此方法仅当属性不能在实例的dict或其父类的 dict中找到时,才被调用
class Person:
def __getattr__(self, item):
return item # 查找不到属性时候返回
p = Person()
print(p.age)
>>age
Tip:item
为查询的属性字符串
-
__getattribute__
当实现了__getattribute__
后,当属性不能在实例的dict或其父类的 dict中找到时,会先去查找__getattribute__
。
一般时候不会去实现该方法,当实现该方法后,不会去查询__getattr__
方法。
属性描述符
- 首先需要知道@property的用法
class Person:
def __init__(self):
self.__age = 10
def age(self):
return self.__age
def set_age(self, age):
if not isinstance(age, int):
raise TypeError("TypeError")
self.__age = age
def del_age(self):
self.__age = None
age = property(fget=age, fset=set_age, fdel=del_age)
if __name__ == '__main__':
p = Person()
p.age = 33
print(p.age)
@property装饰器就是负责把一个方法变成属性调用.
多个属性都需要判断,那么就需要写多个方法,所以就会用到属性描述符,property 其实是一种属性描述符
- 属性描述符:只要实现了
__get__
,__set__
,__delete__
任何一个方法,就被称为属性描述符
class CharTextField():
def __get__(self, instance, owner):
return self.info
def __set__(self, instance, value):
"""
:param instance: 类对象
:param value: 值
"""
if value.isalpha(): # 判断是否为字母
self.info = value
else:
raise TypeError
def __delete__(self, instance):
pass
class Person:
name = CharTextField()
这样就可以批量生成属性并且不用重复判断,并且描述符类能够继承
属性查找顺序
- 当获取类实例化的属性时,查找顺序
Person().name
- 如果
name
出现在类或其基类的__dict__
中, 且name
是data descriptor,那么调用其__get__
方法 - 如果
name
出现在Person
的__dict__
中, 那么直接返回obj.__dict__['name']
- 如果
name
出现在Person
或其基类的__dict__
中- 如果
name
是non-data descriptor,那么调用其__get__
方法 - 返回
__dict__['name']
- 如果
- 如果
Person
有__getattribute__
方法,调用__getattribute__
方法 - 如果
Person
有__getattr__
方法,调用__getattr__
方法 - 抛出
AttributeError
自定义元类
使用type创建动态类
type('object',(),{})
"""
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
"""
- name:创建的类名称
- bases:所继承的父类(Python支持多重继承,所以以元组形式)
- dict:动态绑定属性和方法(
__dict__
)
def get_age(self): # 要加self形参
return "18"
User = type("User", (object), {'name': 'user1', 'getAge': get_age}) # 动态创建并绑定属性和方法
print(User().getAge())
>> 18
动态创建支持继承父类的方法和属性
metaclass属性
- 如果一个类中定义了metalass = xxx,Python就会用元类的方式来创建类
class MetaClass(type):
def __new__(newcls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
return type.__new__(newcls, name, bases, attrs)
# 类的实例化 首先寻找metaclass
class Person(object, metaclass=MetaClass):
"""
Person
"""
网友评论