了解一下 Python 的描述符

简介: 了解一下 Python 的描述符

类里的三个属性,math、chinese、english,都使用了 Property 对属性的合法性进行了有效控制。功能上,没有问题,但就是太啰嗦了,三个变量的合法性逻辑都是一样的,只要大于0,小于100 就可以,代码重复率太高了,这里三个成绩还好,但假设还有地理、生物、历史、化学等十几门的成绩呢?

了解一下 Python 的描述符。

一个实现了 描述符协议 的类就是一个描述符。

什么描述符协议:实现了 __get__()、__set__()、__delete__() 其中至少一个方法的类,就是一个描述符。

__get__: 用于访问属性。它返回属性的值,若属性不存在、不合法等都可以抛出对应的异常。
__set__:将在属性分配操作中调用。不会返回任何内容。
__delete__:控制删除操作。不会返回内容。
下面的Score 类是一个描述器,当从 Student 的实例访问 math、chinese、english这三个属性的时候,都会经过 Score 类里的三个特殊的方法。这里的 Score 避免了 使用Property 出现大量的代码无法复用的尴尬。
class Score:

def __init__(self, default=0):
    self._score = default

def __set__(self, instance, value):
    if not isinstance(value, int):
        raise TypeError('Score must be integer')
    if not 0 <= value <= 100:
        raise ValueError('Valid value must be in [0, 100]')

    self._score = value

def __get__(self, instance, owner):
    return self._score

def __delete__(self):
    del self._score

class Student:

math = Score(0)
chinese = Score(0)
english = Score(0)

def __init__(self, name, math, chinese, english):
    self.name = name
    self.math = math
    self.chinese = chinese
    self.english = english


def __repr__(self):
    return "<Student: {}, math:{}, chinese: {}, english:{}>".format(
            self.name, self.math, self.chinese, self.english
        )

实现的效果和前面的一样,可以对数据的合法性进行有效控制(字段类型、数值区间等)

image.png

参考 https://juejin.im/post/5cc4fbc0f265da0380437706

描述器应用---验证参数类型

class Typed:

def __init__(self, key, expected_type):  # 构造函数接收所传入的参数和参数类型
    self.key = key
    self.expected_type = expected_type

def __get__(self, instance, owner):
    print('get方法')
    return instance.__dict__[self.key]  # 从底层字典获取值

def __set__(self, instance, value):
    print('set方法')
    if not isinstance(value, self.expected_type):  # 类型判断
        raise TypeError('%s 传入的类型不是%s' % (self.key, self.expected_type)) # 格式化抛出异常
    instance.__dict__[self.key] = value # 修改底层字典

def __delete__(self, instance):
    print('delete方法')
    instance.__dict__.pop(self.key)

class People:

name = Typed('name', str)  # p1.__set__()  self.__set__(),触发描述符__set__方法,设置参数类型传给构造函数
age = Typed('age', int)  # p1.__set__()  self.__set__()
salary = Typed('salary', float)  # p1.__set__()  self.__set__()
def __init__(self, name, age, salary):
    self.name = name
    self.age = age
    self.salary = salary

p1=People('alex','13',13.3)#类型有误,报错

p1 = People('alex', 13, 13.3)
print(p1.__dict__)
print(p1.name)
p1.name = 'egon'
print(p1.__dict__)
del p1.name
print(p1.__dict__)

print(p1.name) # 相应的键值对已在底层字典中删除了,报错

相关文章
|
3月前
|
缓存 Python
什么是Python中的描述符(Descriptor)?如何实现一个描述符?
什么是Python中的描述符(Descriptor)?如何实现一个描述符?
42 2
|
安全 数据安全/隐私保护 Python
Python中的描述符:理解并利用其强大的功能
Python是一种动态类型语言,这意味着我们可以在运行时更改对象的结构,例如添加或删除属性。然而,这种灵活性有时可能会导致问题,例如我们可能无意中改变了一个属性的值,或者误用了一个应该是只读的属性。为了解决这些问题,Python提供了一个强大的特性:描述符。
|
Python
Python描述符(__get__和__set__和__delete__)
Python描述符(__get__和__set__和__delete__)
99 0
|
数据安全/隐私保护 Python
python描述符学习
目录 一、对象属性的访问控制 二、描述符基本理解 三、基本使用 四、使用描述符完成property、classmethod、staticmethod自定义实现 1、property的自定义实现 2、classmethod的自定义实现 3、关于实例方法的思考 4、实例方法的自定义实现 5、静态方法的自定义实现 五、总结 一、对象属性的访问控制 看一下这个例子,我们创建一个学生类,提供名字和年龄的属性,然后实例化一个对象,并显示他的信息。
|
Python 程序员 容器
|
8天前
|
算法 程序员 开发工具
百万级Python讲师又一力作!Python编程轻松进阶,豆瓣评分8.1
在学习Python的旅程中你是否正在“绝望的沙漠”里徘徊? 学完基础教程的你,是否还在为选择什么学习资料犹豫不决,不知从何入手,提高自己?
百万级Python讲师又一力作!Python编程轻松进阶,豆瓣评分8.1
|
1天前
|
Shell 数据处理 C++
【震撼揭秘】Python正则VS Shell正则:一场跨越编程边界的史诗级对决!你绝不能错过的精彩较量,带你领略文本处理的极致魅力!
【8月更文挑战第19天】正则表达式是文本处理的强大工具,在Python与Shell中有广泛应用。两者虽语法各异,但仍共享许多基本元素,如`.`、`*`及`[]`等。Python通过`re`模块支持丰富的功能,如非捕获组及命名捕获组;而Shell则依赖`grep`、`sed`和`awk`等命令实现类似效果。尽管Python提供了更高级的特性和函数,Shell在处理文本文件方面仍有其独特优势。选择合适工具需根据具体需求和个人偏好决定。
|
6天前
|
算法 程序员 开发工具
百万级Python讲师又一力作!Python编程轻松进阶,豆瓣评分8.1
在学习Python的旅程中你是否正在“绝望的沙漠”里徘徊? 学完基础教程的你,是否还在为选择什么学习资料犹豫不决,不知从何入手,提高自己?
|
3天前
|
数据采集 存储 人工智能
掌握Python编程:从基础到进阶的实用指南
【8月更文挑战第17天】 本文旨在通过浅显易懂的语言和实际案例,为初学者和有一定基础的开发者提供一条清晰的Python学习路径。我们将从Python的基本语法入手,逐步深入到面向对象编程、数据科学应用及网络爬虫开发等高级主题。每个部分都配备了代码示例和实操建议,确保读者能够将理论知识转化为实际能力。无论你是编程新手,还是希望提升Python技能的开发者,这篇文章都将为你打开一扇通往高效编程世界的大门。
7 2