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

解释 Python 中的描述符(Descriptor)是什么?如何在 Python 中实现一个简单的 ORM(对象关系映射)?

解释 Python 中的描述符(Descriptor)是什么?举例说明其用法。

在 Python 中,描述符(Descriptor)是一种对象属性的扩展机制,它允许你在访问或修改属性时执行自定义的操作。描述符是实现了特定协议的对象,其中包括 getsetdelete 方法。它们通常被用于实现属性的访问控制和行为定制。

描述符的基本用法:
get 方法: 当通过实例访问属性时调用,用于获取属性的值。

set 方法: 当通过实例设置属性值时调用,用于设置属性的值。

delete 方法: 当通过 del 删除属性时调用,用于删除属性。

以下是一个简单的描述符示例:

class DescriptorExample:
    def __init__(self, initial_value=None, name='var'):
        self.value = initial_value
        self.name = name

    def __get__(self, instance, owner):
        print(f'Getting the value of {self.name}')
        return self.value

    def __set__(self, instance, value):
        print(f'Setting the value of {self.name} to {value}')
        self.value = value

    def __delete__(self, instance):
        print(f'Deleting {self.name}')
        del self.value

class MyClass:
    x = DescriptorExample(initial_value=10, name='x')

# 示例使用
obj = MyClass()
obj.x  # 输出: Getting the value of x
obj.x = 20  # 输出: Setting the value of x to 20
del obj.x  # 输出: Deleting x

在上面的示例中,DescriptorExample 类是一个描述符,它被用于控制 MyClass 类中属性 x 的访问和设置。当访问、设置或删除属性时,对应的 getsetdelete 方法会被调用,从而允许我们在属性访问过程中执行自定义的逻辑。

描述符的实际应用:
属性验证和控制: 描述符可以用于验证和控制属性的值,确保其满足特定的条件。

延迟计算: 描述符可以用于实现属性的延迟计算,只有在需要时才计算属性的值。

触发器: 描述符可以用于实现触发器,即在属性访问或修改时执行额外的操作。

缓存属性: 描述符可以用于缓存属性值,避免重复计算。

总体来说,描述符为 Python 提供了一种强大的机制,允许开发者在属性访问过程中插入自定义的行为,从而实现更灵活和定制化的属性管理。

如何在 Python 中实现一个简单的 ORM(对象关系映射)?

对象关系映射(ORM)是一种将数据库中的关系数据映射到对象模型的技术。在 Python 中,可以使用各种 ORM 框架(例如 SQLAlchemy、Django ORM)来简化数据库操作。以下是一个简单的示例,演示如何用 Python 原生代码实现一个基本的 ORM。

import sqlite3

class ORM:
    def __init__(self, db_name):
        self.conn = sqlite3.connect(db_name)
        self.cursor = self.conn.cursor()

    def create_table(self, table_name, columns):
        # 创建表
        columns_str = ', '.join(columns)
        query = f"CREATE TABLE IF NOT EXISTS {table_name} ({columns_str})"
        self.cursor.execute(query)
        self.conn.commit()

    def insert(self, table_name, data):
        # 插入数据
        keys = ', '.join(data.keys())
        values = ', '.join([f"'{value}'" for value in data.values()])
        query = f"INSERT INTO {table_name} ({keys}) VALUES ({values})"
        self.cursor.execute(query)
        self.conn.commit()

    def select_all(self, table_name):
        # 查询所有数据
        query = f"SELECT * FROM {table_name}"
        self.cursor.execute(query)
        return self.cursor.fetchall()

    def close_connection(self):
        # 关闭数据库连接
        self.conn.close()

# 示例使用
if __name__ == "__main__":
    # 创建 ORM 实例
    orm = ORM('example.db')

    # 定义表结构
    table_name = 'users'
    columns = ['id INTEGER PRIMARY KEY', 'username TEXT', 'email TEXT']

    # 创建表
    orm.create_table(table_name, columns)

    # 插入数据
    user_data = {'username': 'john_doe', 'email': 'john@example.com'}
    orm.insert(table_name, user_data)

    # 查询所有数据
    all_users = orm.select_all(table_name)
    print(all_users)

    # 关闭数据库连接
    orm.close_connection()

上述代码简单地实现了一个基本的 ORM,用于操作 SQLite 数据库。在实际项目中,使用成熟的 ORM 框架是更好的选择,因为它们提供了更多的功能和性能优化。例如,使用 SQLAlchemy:

from sqlalchemy import create_engine, Column, Integer, String, MetaData
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    username = Column(String)
    email = Column(String)

# 使用 SQLAlchemy 创建表和操作数据
engine = create_engine('sqlite:///example_orm.db')
Base.metadata.create_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

new_user = User(username='john_doe', email='john@example.com')
session.add(new_user)
session.commit()

all_users = session.query(User).all()
print(all_users)

这里使用 SQLAlchemy 进行了更高级的 ORM 操作,包括定义模型类、创建表结构和插入数据。


http://www.kler.cn/a/227800.html

相关文章:

  • UE5.3 C++ CDO的初步理解
  • OpenCV 版本不兼容导致的问题
  • AJAX综合案例——图书管理
  • 商密测评题库详解:商用密码应用安全性评估从业人员考核题库详细解析(8)
  • 使用langchain ollama gradio搭建一个本地基于deepseek r1的RAG问答系统
  • 基于阿里云百炼大模型Sensevoice-1的语音识别与文本保存工具开发
  • Golang中的HTTP请求凝聚器
  • C语言标准库所有字符串操作库函数汇总
  • ruoyi(若依)(el-menu也可参考)菜单栏过长显示省略号才显示气泡
  • SVDiff: Compact Parameter Space for Diffusion Fine-Tuning——【论文笔记】
  • 聊聊PowerJob的ContainerController
  • Vue中跨域问题的解决
  • 红队渗透靶机:LORD OF THE ROOT: 1.0.1
  • 聊聊并发编程,另送5本Golang并发编程新书
  • LeetCode--代码详解 1.两数之和
  • 为 Windows10 22H2 启用 Microsoft Copilot 功能
  • Android 中的卡顿优化
  • 【JavaEE进阶】 图书管理系统开发日记——肆
  • 1452 - Cannot add or update a child row
  • ES证书过期,错误信息: current license is non-compliant for [security]
  • 大数据信用报告在线查询平台哪个好?
  • [python]基于LSTR车道线实时检测onnx部署
  • 13.2 Web与Servlet进阶(❤❤)
  • Redis(十一)单线程VS多线程
  • [机缘参悟-145] :一个软件架构师对佛学的理解 -9- 修行的目标和层次:净心、智慧和解脱
  • 后端返回给前端的数据格式有哪些?