Python元类编程(高级编程四)
####getattr和getattribute魔法函数
– __getattr__
此方法仅当属性不能在实例的dict或其父类的 dict中找到时,才被调用
1 2 3 4 5 6 7 8 |
class Person: def __getattr__(self, item): return item # 查找不到属性时候返回 p = Person() print(p.age) >>age |
Tip:item
为查询的属性字符串
– __getattribute__
当实现了__getattribute__
后,当属性不能在实例的dict或其父类的 dict中找到时,会先去查找__getattribute__
。
一般时候不会去实现该方法,当实现该方法后,不会去查询__getattr__
方法。
属性描述符
- 首先需要知道@property的用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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__
任何一个方法,就被称为属性描述符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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',(),{})
1 2 3 4 5 6 |
""" type(object_or_name, bases, dict) type(object) -> the object's type type(name, bases, dict) -> a new type """ |
- name:创建的类名称
- bases:所继承的父类(Python支持多重继承,所以以元组形式)
- dict:动态绑定属性和方法(
__dict__
)
1 2 3 4 5 6 7 8 |
def get_age(self): # 要加self形参 return "18" User = type("User", (object), {'name': 'user1', 'getAge': get_age}) # 动态创建并绑定属性和方法 print(User().getAge()) >> 18 |
动态创建支持继承父类的方法和属性
metaclass属性
- 如果一个类中定义了metalass = xxx,Python就会用元类的方式来创建类
1 2 3 4 5 6 7 8 9 10 11 |
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 """ |
Leave a Comment