本文共 3480 字,大约阅读时间需要 11 分钟。
通过使用property
可以将方法像属性一样获取值。使用setter
对方法进行赋值操作
from datetime import datetime, dateclass Student: def __init__(self, name, birthday): self.name = name self.birthday = birthday self._age = 0 @property def age(self): return datetime.now().year - self.birthday.year @age.setter def age(self, value): self._age = value stu = Student("zhangsan", date(year=1995, month=3, day=7))stu.age = 4print(stu.age)output: 24
__getattr__
在类中找不到属性时,调用该函数。
__getattribute__
首先调用该函数,然后找属性. 在__getattribute__
中抛出AttributeError
时,会调用__getattr__
调用顺序
__getattribute__
> __getattr__
在类中只要实现了__get__
、__set__
、__delete__
方法中的一个就认为是描述符
.
__get__
的对象是非数据描述符
. 只读 实现了__get__
和__set__
的对象是数据描述符
. 可读可写. class IntField: def __get__(self): pass def __set__(self): pass def __delete__(self): pass
属性描述符发生的过程在__getattribute__
中.
如果age是属性描述符,则调用IntField
中的__get__
获得属性值,如果获取失败,则调用__dict__
获取值。如果age不是属性描述符,则直接获取__dict__
对应的值。
import numbersclass IntField: # 数据描述符 def __get__(self, instance, owner): return self.value def __set__(self, instance, value): if not isinstance(value, numbers.Integral): raise ValueError("int value need") if value < 0: raise ValueError("positive value need") self.value = value def __delete__(self, instance): pass class NonDataIntField: # 非数据属性描述符 def __get__(self, instance, owner): return "NonDataIntField = {}".format(self.value)class User: age = IntField() #age = NonDataIntField()user = User()user.name = "zhangsan" # name不是属性描述符,所以直接加入到`__dict__`中print(user.__dict__)user.age = 12 # age是属性描述符, 调用`IntField`中的`__set__`方法, 而不会加入到`__dict__`中print(user.__dict__)print(user.age) # 调用`IntField`中的`__get__`方法
元类是创建类的类.
type -> class -> 对象所有的类都是通过type实例化得到的。
使用type创建User
类,该类继承Base
类,并且有test
方法和name
属性
class Base: def __init__(self, *args, **kwargs): print("Base __init__") super().__init__(*args, **kwargs)def test(self): print("test = {}".format(self.name)) User = type("User", (Base,), { "test": test, "name": "zhangsan"})user = User()user.test()
自定义元类需要通过继承type
实现
如果父类有metaclass,则子类和父类的创建都需要通过该元类实例化得到。
class BaseMeta(type): def __new__(cls, name, bases, args, **kwargs): # print(name) # print(bases) # print(args) print("BaseMeta __new__..") if name == "Base": return super().__new__(cls, name, bases, args, **kwargs) meta = args['Meta'] name = getattr(meta, "name") # 获取到A中meta的name的值. django的orm也是这样实现的 print(name) return super().__new__(cls, name, bases, args, **kwargs)class Base(metaclass=BaseMeta): def __new__(cls, *args, **kwargs): print("Base __new__..") return super().__new__(cls, *args, **kwargs) def __init__(self, *args, **kwargs): print("Base init..") super().__init__(*args, **kwargs) class A(Base): def __new__(cls, *args, **kwargs): print("A __new__..") return super().__new__(cls, *args, **kwargs) def __init__(self, *args, **kwargs): print("A init..") super().__init__(*args, **kwargs) class Meta: name = "zhangsan"# A和Base都会通过BaseMeta创建,所以会调用两次__new__创建实例output:BaseMeta __new__..BaseMeta __new__..zhangsan
元类的经典例子是django ORM
转载地址:http://wakjn.baihongyu.com/