当前位置: 首页 > news >正文

商业空间设计方案/快速整站优化

商业空间设计方案,快速整站优化,沈阳旅游团购网站建设,网上110在线咨询Python 入门 —— 描述器 文章目录 Python 入门 —— 描述器描述器简单示例定制名称只读属性状态交互验证器类自定义验证器验证器的使用 对象关系映射 描述器 前面我们介绍了两种属性拦截的方式:特性(property)以及重载属性访问运算符&#…

Python 入门 —— 描述器

文章目录

  • Python 入门 —— 描述器
    • 描述器
      • 简单示例
      • 定制名称
      • 只读属性
      • 状态交互
      • 验证器类
        • 自定义验证器
        • 验证器的使用
      • 对象关系映射

描述器

前面我们介绍了两种属性拦截的方式:特性(property)以及重载属性访问运算符,还有一种方式是通过描述器来拦截属性访问,特性只是一种特定类型的描述器的简化使用方式,而描述器也是由 __getattribute__ 函数调用。

描述器允许我们把特定属性的 getsetdel 操作指向独立的类对象方法,使对象能够自定义属性查找、存储和删除操作。

任何实现了:__get____set____delete__ 方法中的一种的类都可以称为描述器。

描述器的主要目的是提供一个挂钩,允许存储在类变量中的对象控制在属性查找期间发生的情况。

传统上,调用类控制查找过程中发生的事情。但描述器反转了这种关系,并允许正在被查询的数据对此进行干涉。

简单示例

class Name:"""Name descriptor doc"""def __get__(self, obj, objtype=None):print('get')return obj._namedef __set__(self, obj, value):print('set')obj._name = valuedef __delete__(self, obj):print('del')del obj._nameclass Person:name = Name()def __init__(self, name):self.name = nametom = Person('Tom')
# set
tom.name
# get
# 'Tom'
tom.name = 'Robert'
# set
tom.name
# get
# 'Robert'
vars(tom)
# {'_name': 'Robert'}
del tom.name
# del

虽然我们为 Person 定义了 name 属性,但是存储在 __dict__ 中的还是 _name(与 Name 描述符中使用的属性一致)。

注意

必须将描述符赋值给一个类属性,如果赋值为实例属性,将无法工作,可以自己尝试一下。注意这三个方法的参数,obj 表示 Person 类实例对象,objtype 默认为 Person

定制名称

在上面的例子中,我们定义的描述符只能用于 _name 属性,但是一般我们所定义的描述符都希望其能够适用于更多的属性,这显然不符合我们实际的需求。

我们可以添加 __set_name__ 方法来记录字段名称,让每个描述符都有自己的公有属性和私有属性名称,例如

class Field:def __set_name__(self, owner, attr):self.public_name = attrself.private_name = '_' + attrdef __get__(self, obj, objtype=None):value = getattr(obj, self.private_name)print('Accessing', self.public_name)return valuedef __set__(self, obj, value):print('Updating', self.public_name, 'to', value)setattr(obj, self.private_name, value)class Person:name = Field()age = Field()def __init__(self, name, age):self.name = nameself.age = agetom = Person('Tom', 19)
# Updating name to Tom
# Updating age to 19
tom.name
# Accessing name
# 'Tom'
vars(tom)
# {'_name': 'Tom', '_age': 19}
tom._name
# 'Tom'
vars(vars(Person)['name'])
# {'public_name': 'name', 'private_name': '_name'}

其中 owner 是使用描述器的类,name 是分配给描述器的类变量名。

vars 函数只是查找属性并不会触发方法,访问私有属性也不会经过描述符。

只读属性

使用描述符来创建只读属性,光定义 __get__ 方法,而没有定义 __set__ 是不够的,例如

class TestDesc:def __get__(self, obj, obj_type=None):print('Get')class Test:t = TestDesc()a = Test()
a.t
# Get
vars(a)
# {}
a.t = 100
a.t
# 100
vars(a)
# {'t': 100}

对描述符属性赋值会将其覆盖,可以看到赋值后出现了一个常规的公开属性,要设置只读属性,要在 __set__ 方法中让赋值行为引发一个异常

class TestDesc:def __get__(self, obj, obj_type=None):print('Get')def __set__(self, obj, value):raise AttributeError("Con't set value!")class Test:t = TestDesc()a = Test()
a.t
# Get
a.t = 100
# AttributeError: Con't set value!

状态交互

描述符内也可以定义属性值,在 __get____set__ 函数内也可以使用实例参数来获取包含描述符的类的属性值

class Money:def __init__(self, value):self.value = valuedef __get__(self, obj, obj_type=None):return self.value * getattr(obj, 'rate')def __set__(self, obj, value):self.value = valueclass Exchange:money = Money(1000)def __init__(self, rate):self.rate = rates = Exchange(0.567)
s.money
# 567.0
s.rate = 0.678
s.money
# 678.0

上面这段代码,属性 value 仅存在于描述符中,并不会与使用描述符的类中的属性有冲突。money 属性会随着 rate 值的变化自动计算出相应的值。

验证器类

验证器是一个用于托管属性访问的描述器。在存储任何数据之前,它会验证新值是否满足各种类型和范围限制。如果不满足这些限制,它将引发异常,从源头上防止数据损坏。

这一功能通常在前后端数据校验中比较常用,我们可以自己实现一个验证器。例如,我们定义一个抽象类,必须实现 validate 方法

from abc import ABC, abstractmethodclass Validator(ABC):def __set_name__(self, owner, name):self.private_name = '_' + namedef __get__(self, obj, objtype=None):return getattr(obj, self.private_name)def __set__(self, obj, value):self.validate(value)setattr(obj, self.private_name, value)@abstractmethoddef validate(self, value):pass
自定义验证器

我们可以对数据进行常见的几种校验,例如:

  • OneOf:验证值是一组受约束的选项之一。
class OneOf(Validator):def __init__(self, *options):self.options = set(options)def validate(self, value):if value not in self.options:raise ValueError(f'Expected {value!r} to be one of {self.options!r}')
  • Number:验证值是否为 intfloat。根据可选参数,它还可以验证值在给定的最小值或最大值之间。
class Number(Validator):def __init__(self, minvalue=None, maxvalue=None):self.minvalue = minvalueself.maxvalue = maxvaluedef validate(self, value):if not isinstance(value, (int, float)):raise TypeError(f'Expected {value!r} to be an int or float')if self.minvalue is not None and value < self.minvalue:raise ValueError(f'Expected {value!r} to be at least {self.minvalue!r}')if self.maxvalue is not None and value > self.maxvalue:raise ValueError(f'Expected {value!r} to be no more than {self.maxvalue!r}')
  • String:验证值是否为 str。根据可选参数,它可以验证给定的最小或最大长度,还可以验证用户定义的 predicate
class String(Validator):def __init__(self, minsize=None, maxsize=None, predicate=None):self.minsize = minsizeself.maxsize = maxsizeself.predicate = predicatedef validate(self, value):if not isinstance(value, str):raise TypeError(f'Expected {value!r} to be an str')if self.minsize is not None and len(value) < self.minsize:raise ValueError(f'Expected {value!r} to be no smaller than {self.minsize!r}')if self.maxsize is not None and len(value) > self.maxsize:raise ValueError(f'Expected {value!r} to be no bigger than {self.maxsize!r}')if self.predicate is not None and not self.predicate(value):raise ValueError(f'Expected {self.predicate} to be true for {value!r}')
验证器的使用

我们定义一个类,包含三种带验证器的描述器属性

class Component:name = String(minsize=3, maxsize=10, predicate=str.isupper)kind = OneOf('wood', 'metal', 'plastic')quantity = Number(minvalue=0)def __init__(self, name, kind, quantity):self.name = nameself.kind = kindself.quantity = quantity

描述器会阻止错误实例的创建

Component('Widget', 'metal', 5)      # 'Widget' 不是全大写
# Traceback (most recent call last):
#     ...
# ValueError: Expected <method 'isupper' of 'str' objects> to be true for 'Widget'Component('WIDGET', 'metle', 5)      # 'metle' 不在取值范围
# Traceback (most recent call last):
#     ...
# ValueError: Expected 'metle' to be one of {'metal', 'plastic', 'wood'}Component('WIDGET', 'metal', -5)     # quantity 的值要大于等于 0
# Traceback (most recent call last):
#     ...
# ValueError: Expected -5 to be at least 0
Component('WIDGET', 'metal', 'V')    # quantity 不是数值
# Traceback (most recent call last):
#     ...
# TypeError: Expected 'V' to be an int or floatc = Component('WIDGET', 'metal', 5)  # 通过

对象关系映射

我们可以使用描述器来实现一个简单的对象关系映射(ORM)框架

其核心思路是将数据存储在外部数据库中,Python 实例仅持有数据库表中对应的的键,描述器负责对值进行查找或更新。

我们首先定义字段描述器

class Field:def __set_name__(self, owner, name):self.fetch = f'SELECT {name} FROM {owner.table} WHERE {owner.key}=?;'self.store = f'UPDATE {owner.table} SET {name}=? WHERE {owner.key}=?;'def __get__(self, obj, objtype=None):return conn.execute(self.fetch, [obj.key]).fetchone()[0]def __set__(self, obj, value):conn.execute(self.store, [value, obj.key])conn.commit()

然后用 Field 类来定义描述了数据库中每张表的模式(models)。

class Movie:table = 'Movies'                    # Table namekey = 'title'                       # Primary keydirector = Field()year = Field()def __init__(self, key):self.key = keyclass Song:table = 'Music'key = 'title'artist = Field()year = Field()genre = Field()def __init__(self, key):self.key = key

要使用模型,首先要创建一个数据库

def create_tables(conn):with conn:conn.execute('''CREATE TABLE IF NOT EXISTS Movies (title TEXT PRIMARY KEY,director TEXT,year INTEGER)''')conn.execute('''CREATE TABLE IF NOT EXISTS Music (title TEXT PRIMARY KEY,artist TEXT,year INTEGER,genre TEXT)''')def insert_movie(conn, title, director, year):with conn:conn.execute('''INSERT INTO Movies (title, director, year) VALUES (?, ?, ?)''', (title, director, year))def insert_song(conn, title, artist, year, genre):with conn:conn.execute('''INSERT INTO Music (title, artist, year, genre) VALUES (?, ?, ?, ?)''', (title, artist, year, genre))conn = sqlite3.connect('example.db')
create_tables(conn)insert_movie(conn, 'Inception', 'Christopher Nolan', 2010)
insert_movie(conn, 'The Matrix', 'Lana Wachowski, Lilly Wachowski', 1999)insert_song(conn, 'Bohemian Rhapsody', 'Queen', 1975, 'Rock')
insert_song(conn, 'Imagine', 'John Lennon', 1971, 'Pop')

从数据库中检索数据及对其进行更新

Movie('Inception').director
# 'Christopher Nolan'
mat = Movie('The Matrix')
f'Released in {mat.year} by {mat.director}'
# 'Released in 1999 by Lana Wachowski, Lilly Wachowski'Song('Imagine').artist
# 'John Lennon'Movie('Inception').director = 'Nolan'
Movie('Inception').director
# 'Nolan'

关闭数据库连接

conn.close()

相关文章:

Python 入门 —— 描述器

Python 入门 —— 描述器 文章目录 Python 入门 —— 描述器描述器简单示例定制名称只读属性状态交互验证器类自定义验证器验证器的使用 对象关系映射 描述器 前面我们介绍了两种属性拦截的方式&#xff1a;特性&#xff08;property&#xff09;以及重载属性访问运算符&#…...

测试驱动开发TDD

如何在后端测试代码&#xff0c;测试一个其前端的请求&#xff0c;能否正常处理 以登录请求为例 package com.example.demo.login;import com.example.demo.login.pojo.User; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; import…...

[论文笔记]Mixture-of-Agents Enhances Large Language Model Capabilities

引言 今天带来一篇多智能体的论文笔记&#xff0c;Mixture-of-Agents Enhances Large Language Model Capabilities。 随着LLMs数量的增加&#xff0c;如何利用多个LLMs的集体专业知识是一个令人兴奋的开放方向。为了实现这个目标&#xff0c;作者提出了一种新的方法&#xf…...

Redis 7.x 系列【6】数据类型之字符串(String)

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 前言2. 常用命令2.1 SET2.2 GET2.3 MSET2.4 MGET2.5 GETSET2.6 STRLEN2.7 SETEX2.8…...

指针(一)

指针基础 在C中&#xff0c;指针是至关重要的组成部分。它是C语言最强大的功能之一&#xff0c;也是最棘手的功能之一。 指针具有强大的能力&#xff0c;其本质是协助程序员完成内存的直接操纵。 指针&#xff1a;特定类型数据在内存中的存储地址&#xff0c;即内存地址。 …...

harmony鸿蒙下实现bc交互的方式和方法

前言 最近在研究harmony操作系统下的交互&#xff0c;因此写一篇文章记录一下。 解决的问题 本篇文章主要是来写解决如果兼容android或者ios的交互&#xff0c;这样子避免h5页面的二次开发&#xff0c;节省资源。 交互的种类 交互对于harmony来说其实只有一种&#xff0c;…...

【MySQL进阶之路 | 高级篇】索引的声明与使用

1. 索引的分类 MySQL的索引包括普通索引&#xff0c;唯一性索引&#xff0c;全文索引&#xff0c;单列索引和空间索引. 从功能逻辑上说&#xff0c;索引主要分为普通索引&#xff0c;唯一索引&#xff0c;主键索引和全文索引.按物理实现方式&#xff0c;索引可以分为聚簇索引…...

探索Java中的设计模式:从单例到工厂模式

探索Java中的设计模式&#xff1a;从单例到工厂模式 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨Java中的设计模式&#xff0c;从经典的单…...

表单(forms)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在app1文件夹下创建一个forms.py文件&#xff0c;添加如下类代码&#xff1a; from django import forms class PersonForm(forms.Form): first_na…...

Geoserver源码解读四 REST服务

文章目录 文章目录 一、概要 二、前置知识点-FreeMarker 三、前置知识点-AbstractHttpMessageConverter 3.1 描述 3.2 应用 四、前置知识点-AbstractDecorator 4.1描述 4.2 应用 五、工作空间查询解读 5.1 模板解读 5.2 请求转换器解读 一、概要 关于geoserver的r…...

硬件开发笔记(二十一):外部搜索不到的元器件封装可尝试使用AD21软件的“ManufacturerPart Search”功能

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/139869584 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…...

【AI大模型】GPTS 与 Assistants API

前言 2023 年 11 月 6 日&#xff0c;OpenAI DevDay 发表了一系列新能力&#xff0c;其中包括&#xff1a;GPT Store 和 Assistants API。 GPTs 和 Assistants API 本质是降低开发门槛 可操控性和易用性之间的权衡与折中&#xff1a; 更多技术路线选择&#xff1a;原生 API、…...

攻击者开始使用 XLL 文件进行攻击

近期&#xff0c;研究人员发现使用恶意 Microsoft Excel 加载项&#xff08;XLL&#xff09;文件发起攻击的行动有所增加&#xff0c;这项技术的 MITRE ATT&CK 技术项编号为 T1137.006。 这些加载项都是为了使用户能够利用高性能函数&#xff0c;为 Excel 工作表提供 API …...

Why RAG is slower than LLM?

I used RAG with LLAMA3 for AI bot. I find RAG with chromadb is much slower than call LLM itself. Following the test result, with just one simple web page about 1000 words, it takes more than 2 seconds for retrieving: 我使用RAG&#xff08;可能是指某种特定的…...

Word页码设置,封面无页码,目录摘要阿拉伯数字I,II,III页码,正文开始123为页码

一、背景 使用Word写项目书或论文时&#xff0c;需要正确插入页码&#xff0c;比如封面无页码&#xff0c;目录摘要阿拉伯数字I&#xff0c;II&#xff0c;III为页码&#xff0c;正文开始以123为页码&#xff0c;下面介绍具体实施方法。 所用Word版本&#xff1a;2021 二、W…...

汽车汽配图纸管理、产品研发管理解决方案

汽车汽配图纸管理、产品研发管理解决方案 随着全球汽车市场的快速发展&#xff0c;中国汽车汽配行业迎来了前所未有的发展机遇。然而&#xff0c;在这一过程中&#xff0c;企业也面临着诸多挑战&#xff0c;如研发能力的提升、技术资料管理的复杂性、以及跨部门协作的困难等。为…...

小程序简单版音乐播放器

小程序简单版音乐播放器 结构 先来看看页面结构 <!-- wxml --><!-- 标签页标题 --> <view class"tab"><view class"tab-item {{tab0?active:}}" bindtap"changeItem" data-item"0">音乐推荐</view><…...

驾校预约管理系统

摘 要 随着驾驶技术的普及和交通安全意识的增强&#xff0c;越来越多的人选择参加驾校培训&#xff0c;以获取驾驶执照。然而&#xff0c;驾校管理面临着日益增长的学员数量和繁琐的预约管理工作。为了提高驾校的管理效率和服务质量&#xff0c;驾校预约管理系统成为了必不可少…...

C++ 左值右值 || std::move() || 浅拷贝,深拷贝 || 数据类型

数据类型&#xff1a; 作用&#xff1a;决定变量所占内存空间的字节大小&#xff0c;和布局方式基本数据类型&#xff1a; 算数类型&#xff1a; 整形&#xff08;bool / char……扩展集 / int / long……&#xff09;&& 浮点形&#xff08;float/double……&#xff…...

发那科机器人IO 分配

IO 信号 也称为输入\输出信号&#xff0c;是机器人与外围设备通信的电信号...

ubuntu开机怎么进入、退出命令行界面

要在Ubuntu系统开机时进入命令行界面&#xff0c;可以按照以下步骤操作&#xff1a; 在开机过程中按下Ctrl Alt F1组合键&#xff0c;这将会切换到第一个虚拟控制台&#xff0c;即命令行界面。如果Ctrl Alt F1没有生效&#xff0c;也可以尝试Ctrl Alt F2、Ctrl Alt F3…...

『FPGA通信接口』LVDS接口(4)LVDS接收端设计

文章目录 1.LVDS接收端概述2逻辑框图3.xapp855训练代码解读4.接收端发送端联调5.传送门 1.LVDS接收端概述 接收端的传输模型各个属性应该与LVDS发送端各属性一致&#xff0c;例如&#xff0c;如果用于接收CMOS图像传感器的图像数据&#xff0c;则接收端程序的串化因子、通道个…...

面试题:HTTP的body是二进制还是文本

实际上&#xff0c;HTTP的body可以是二进制数据&#xff0c;也可以是文本。HTTP协议本身不对body内容的格式做限制&#xff0c;具体格式取决于Content-Type头字段的定义。 文本数据&#xff1a; 当Content-Type头字段指定为文本类型时&#xff08;如text/plain、text/html、ap…...

5分钟带你部署一套Jenkins持续集成环境​

5分钟带你部署一套Jenkins持续集成环境 Jenkins是开源CI&CD软件领导者&#xff0c; 提供超过1000个插件来支持构建、部署、自动化&#xff0c; 满足任何项目的需要。 Jenkins的优点 持续集成和持续交付 作为一个可扩展的自动化服务器&#xff0c;Jenkins 可以用作简单的 CI…...

OpenAI突然宣布停止向中国提供API服务!

标题 &#x1f31f; OpenAI突然宣布停止向中国提供API服务! &#x1f31f;摘要 &#x1f4dc;引言 &#x1f4e2;正文 &#x1f4dd;1. OpenAI API的重要性2. 停止服务的原因分析3. 对中国市场的影响4. 应对措施代码案例 &#x1f4c2;常见问题解答&#xff08;QA&#xff09;❓…...

Bootstrap 标签

Bootstrap 标签 引言 Bootstrap 是一个流行的前端框架&#xff0c;它提供了一套丰富的组件和工具&#xff0c;帮助开发者快速构建响应式和移动优先的网页。在 Bootstrap 中&#xff0c;标签&#xff08;Badge&#xff09;是一种小巧的组件&#xff0c;用于显示计数、提示或标…...

EtherCAT主站SOEM -- 37 -- win-soem-win10及win11系统QT-SOEM-1个电机转圈圈-周期同步速度模式(CSV模式)

EtherCAT主站SOEM -- 37 -- win-soem-win10及win11系统QT-SOEM-1个电机转圈圈-周期同步速度模式(CSV模式) 0 QT-SOEM及STM32F767-SOEM视频欣赏及源代码链接:0.1 Linux--Ubuntu系统之 QT-SOEM博客、视频欣赏及源代码链接0.2 STM32F767-SOEM 博客、视频欣赏及源代码链接0.3 wi…...

老板舍不得买库存管理软件❓一招解决

在当今快节奏的商业环境中&#xff0c;仓库管理是企业运作中不可或缺的一环。对于许多中小型企业而言&#xff0c;简易且高效的库存管理系统尤为重要。搭贝简易库存管理系统针对仓库的出入库进行有效管理&#xff0c;帮助企业实现库存的透明化和流程的自动化。 客户的痛点 1. …...

【MySQL数据库】:MySQL视图特性

目录 视图的概念 基本使用 准备测试表 创建视图 修改视图影响基表 修改基表影响视图 删除视图 视图规则和限制 视图的概念 视图是一个虚拟表&#xff0c;其内容由查询定义&#xff0c;同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。视图中的数据…...

malloc、free和new delete的区别

malloc/free 和 new/delete 是在 C 中分配和释放内存的两种不同方法。它们主要有以下区别&#xff1a; 1. 语法和用法 malloc 和 free: malloc开辟空间时需要手动计算分配的空间大小 int* p (int*)malloc(sizeof(int) * 10); // 分配10个int类型的内存 // 使用内存 free(p); …...