以下是用我自己立即的方式去记录关于描述符的认识笔记。纯属整理和实践笔记记录。如有错误,还希望多多指教!
@property() 函数的作用是在新式类中返回属性值(把一个方法变成属性调用)。
class People:
def __init__(self, name=None):
self._name = name
# 使用property,解决显式的类似get_budget和set_budget方法。
@property
def name(self):
"""I'm the 'x' property."""
print("我可以先处理一下相关逻辑再返回")
return self._name
@name.setter
def name(self, value):
print("我可以先处理一下相关逻辑再设置")
self._name = value
@name.deleter
def name(self):
del self._name
# 标记为一个只读的属性值
@property
def age(self):
return 201
p = People()
print(p.name)
print(p.age)
p.name = 345
上面的示例中我们的使用了@property,
property优点:
property缺点:
纯可读属性:定义@property(只实现getter方法,不定义setter方法)
可读书属性:
都定义,是读写属性
1)把属性委托给另一个类进行代理校验,类的方式实现:
#!/usr/bin/evn python
# coding=utf-8
# 描述的类
class Describe:
def __init__(self,a_value):
print("传值:",a_value)
self.key = '我是代理被描述类的属性的代理者'
def __get__(self, instance, value):
print("返回属性", instance, value)
return self.key
# def __set__(self, instance, value):
def __set__(self, instance, value):
print("设置属性", instance, value)
return value
def __delete__(self, instance):
print("删除对象", instance)
del self.key
# 被描述的类
class People:
# 注意这个了类变量==把一个描述类的对象给赋值到被描述的类的属性的变量上
name = Describe("传递参数")
sex = Describe("传递参数sex")
def __init__(self):
# 这里引发了设置属性,但是调用的描述类的属性值,也就是说,是调用了类属性的值,而不是给对象建立一个实例属性
self.name = "上面什么啊"
self.sex = "男"
p = People()
print(p.name)
2)结合setattr和类的装饰器模式+描述符类实现对类属性代理:
class Describe:
'''
描述符类
'''
def __init__(self,attri,data_type):
# 具体的属性
self.attri = attri
# 属性的类型
self.data_type = data_type
def __get__(self, instance, owner):
print(f'get触发了')
if instance is None:
return '当前未通过对象调用描述符的代理'
print("返回属性属性")
return instance.__dict__[self.attri]
def __set__(self, instance, value):
if not isinstance(value, self.data_type):
raise TypeError(f'{self.attri}属性传递的不是:{self.data_type}类型数据')
print("开始设置属性")
instance.__dict__[self.attri] = value
def __delete__(self, instance):
print('执行了delete方法:')
def arrti_datatype_decorate(*args,**kwargs):
'''
类装饰器
:param args:
:param kwargs:
:return:
'''
def decorate(cls):
print(args)
# 设置相关的属性的类型
for attri, data_type in kwargs.items():
# setattr(cls, attri, data_type)
print('有参装饰器!-> %s--类似是:%s' % (attri,data_type))
# 注意这里,将传给类的属性变成代理描述符的类属性
# cls:People这个类
# attri:给People类设置的属性名
# An(attri,data_type) 将属性名与数据类型传递到描述符里的__init__内
# 得到一个代理描述符的对象,然后赋给cls,也就是People类
setattr(cls, attri, Describe(attri, data_type))
# setattr就是给对象增加属性的,类也可以是一个对象,也可以进行属性增加
return cls
return decorate
@arrti_datatype_decorate(435,name = str,age = int,sex = str)
class People:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
# print(People.__dict__)
# 涉及到了三个属性的设置和校验
p = People('jack',18,'444')
p.age = 345
# @arrti_datatype_decorate(435,name = str,age = int,sex = str)
# class People:
# pass
#
# # print(People.__dict__)
# # 涉及到了三个属性的设置和校验
# p = People()
# p.age = 345
# p.name = "sadsad"
输出结果为:
(435,)
有参装饰器!-> name--类似是:<class 'str'>
有参装饰器!-> age--类似是:<class 'int'>
有参装饰器!-> sex--类似是:<class 'str'>
开始设置属性
开始设置属性
开始设置属性
开始设置属性
分析:上面的示例是通过一个装饰器的形式进行批量属性的进行绑定描述符。
从上面看。上面的模式其实和我们的pydantic类型检查工具是差不多的性质的,甚至可以嵌套!
描述符的本质对属性的个性定制与控制:所以通常相关的场景如:
https://blog.csdn.net/qq_27825451/article/details/84848341
https://blog.csdn.net/m0_46958731/article/details/111935453(非常好的参考)
简书:https://www.jianshu.com/u/d6960089b087
掘金:https://juejin.cn/user/2963939079225608
小钟同学 | 文 【原创】| QQ:308711822
1:本文相关描述主要是个人的认知和见解,如有不当之处,还望各位大佬指正。 2:关于文章内容,有部分内容参考自互联网,如有链接会声明标注;如没有及时标注备注的链接的,如有侵权请联系,我会立即删除处理哟。
原文作者:程序员小钟同学;如有侵权,请联系管理员删除。