proterty动态属性
property 作用和应用场景:
- @property 优化了属性读取和设置的可读性
- 需要限制属性的特征;
- 只读属性。如果属性只可以读,不可以写,用起来很方便。
- 这个属性根据一个变化的环境动态改变。
- 举例https://www.cnblogs.com/wagyuze/p/10622561.html
from datetime import datetime, date
class User:
def __init__(self, name, birthday):
self.name = name
self.birthday = birthday
self._age = 0
# def get_age(self):
# return datetime.now().year - self.birthday.year
@property
def age(self):
return datetime.now().year - self.birthday.year
@age.setter
def age(self, value):
self._age = value
if __name__ == "__main__":
user = User("tom", date(year=1987, month=11, day=9))
user.age = 32 # 可以通过这种方式来读写类中的私有属性
print(user._age)
动态属性 @property
from datetime import date, datetime
class User:
def __init__(self, name, birthday):
self.name = name
self.birthday = birthday
self._age = 0 # _代表这个属性不想暴露,代码上的规范。双下滑线隐藏。
@property # 将age方法变为属性 、这个可以理解为get属性
def age(self):
# 获取他的年龄 当年年份-生日
return datetime.now().year - self.birthday.year
@age.setter # user.age=30 会运行这段代码
def age(self, value):
self._age = value
if __name__ == "__main__":
user = User("bobby", date(year=1987, month=1, day=1))
user.age = 30
print (user._age)
print(user.age)
属性描述符和属性的查找过程
"""
IntField 是专门判断是否为整数的类
实现get set delte任何一个魔法函数,IntField 就变为属性描述符
"""
import numbers
class IntField:
"""数据描述符"""
def __get__(self,instance,owner):
return self.value
def __set__(self,instance,value):
# 判断是否为Int类型
if not isinstance(value,numbers.Integral):
raise ValueError("int value need ")
if value<0:
raise ValueError("positive value need ")
self.value = value
pass
def __delete__(self,instance):
pass
class NoneDataIntField:
"""非数据属性描述符"""
def __get__(self,instance,owner):
return self.value
class User:
age = IntField()
if __name__ == "__main__":
user = User()
user.age=30 # 赋值的时候,其实会调用User的set方法。
print(user.age)
"""
属性描述符查找的完整过程
如果user是某个类的实例,那么user.age(以及等价的getattr(user,’age’)) getattr全局
首先调用__getattribute__。如果类定义了__getattr__方法
那么在__getattribute__抛出 AttributeError 的时候就会调用到__getattr__,
而对于描述符(__get__)的调用,则是发生在__getattribute__内部的。
user = User(), 那么user.age 顺序如下:
(1)如果“age”是出现在User或其基类的__dict__中, 且age是data descriptor, 那么调用其__get__方法, 否则
(2)如果“age”出现在user的__dict__中, 那么直接返回 obj.__dict__[‘age’], 否则
(3)如果“age”出现在User或其基类的__dict__中
(3.1)如果age是non-data descriptor,那么调用其__get__方法, 否则
(3.2)返回 __dict__[‘age’]
(4)如果User有__getattr__方法,调用__getattr__方法,否则
(5)抛出AttributeError
"""
__new__ 和 __init__ 的区别
这两个方法的主要区别在于:__new__ 负责对象的创建而 __init__ 负责对象的初始化。在对象的实例化过程中,这两个方法会有些细微的差别,表现于:如何工作,何时定义
1.__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
2.__new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。
但是说了这么多,__new__最通常的用法是什么呢,我们什么时候需要__new__?
自定义元类
元类 # python中一切皆为对象。 # 所有的对象都是实例化或者说调用类而得到的(调用类的过程称为类的实例化) # 基于python中一切皆为对象的概念分析出:我们用class关键字定义的类本身也是一个对象, # 负责产生该对象的类称之为元类(元类可以简称为类的类),内置的元类为type # class关键字在帮我们创建类时,必然帮我们调用了元类OldboyTeacher=type(...),那调用type时传入的参数是什么呢?必然是类的关键组成部分,一个类有三大组成部分,分别是 # 1、类名class_name='OldboyTeacher' # 2、基类们class_bases=(object,) # 3、类的名称空间class_dic,类的名称空间是执行类体代码而得到的 # 调用type时会依次传入以上三个参数 #一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type, # 我们也可以通过继承type来自定义元类,然后使用metaclass关键字参数为一个类指定元 class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
参考文章:
原文链接:https://blog.csdn.net/sunt2018/article/details/88696305
原文链接:https://blog.csdn.net/sunt2018/article/details/88696305