刘心向学(41):描述符(Descriptors)——掌控属性的幕后黑手

B站影视 港台电影 2025-08-31 17:17 2

摘要:但 @property 本质上是一个描述符。Python 中所有 @property、@staticmethod、@classmethod 都是基于描述符机制实现的。

分享兴趣,传播快乐,

增长见闻,留下美好!

亲爱的您,这里是LearningYard新学苑。

今天小编为大家带来文章

“刘心向学(41):描述符(Descriptors)——掌控属性的“幕后黑手””

Share interest, spread happiness,

Increase knowledge, leave a beautiful!

Dear, this is LearningYard Academy.

Today, the editor brings you an article.

“Liu Xin's Learning Notes (41): Descriptors — The "Invisible Hand" Behind Attribute Control”

Welcome to your visit.

你一定用过 @property 来定义“计算属性”:

You must have used @property to define "computed properties":

Python深色版本classCircle:def__init__(self, radius): self.radius = radius @propertydefarea(self):return3.14159 * self.radius ** 2

但 @property 本质上是一个描述符。Python 中所有 @property、@staticmethod、@classmethod 都是基于描述符机制实现的。

However, @property is essentially a descriptor. All built-in decorators in Python such as @property, @staticmethod, and @classmethod are implemented using the descriptor mechanism.

描述符让你能:

Descriptors allow you to:

拦截属性的读取、赋值、删除操作

Intercept attribute access, assignment, and deletion

实现可复用的属性逻辑(跨多个类)

Implement reusable attribute logic (acrossmultiple classes)

构建更智能、更安全的对象系统

Build smarter and safer object systems

掌握描述符,你就掌握了 Python 属性系统的“操作系统级权限”。

Mastering descriptors gives you "operating system-level control" over Python's attribute system.

A descriptor is an object that implements the descriptor protocol, meaning it defines any of the following methods:

__get__(self, obj, owner)

:当获取属性时调用

: Called when an attribute is accessed

__set__(self, obj, value)

:当设置属性时调用

: Called when an attribute is set

__delete__(self, obj)

:当删除属性时调用

: Called when an attribute is deleted

注意:描述符必须定义在类级别,不能是实例属性。

Note: Descriptors must be defined at the class level, not as instance attributes.

Python深色版本classTyped:def__init__(self, expected_type): self.expected_type = expected_typedef__set_name__(self, owner, name): self.name = name # 自动获取属性名def__set__(self, obj, value):ifnotisinstance(value, self.expected_type):raise TypeError(f"{self.name} must be {self.expected_type.__name__}") obj.__dict__[self.name] = value # 存入实例字典def__get__(self, obj, owner):if obj isNone:return selfreturn obj.__dict__.get(self.name)classPerson: name = Typed(str) age = Typed(int)p = Personp.name = "Bob"p.age = 25# p.age = "25" # TypeError: age must be int

Compute the value only on first access, then cache the result:

Python深色版本classLazyProperty:def__init__(self, func): self.func = func self.name = func.__name__def__get__(self, obj, owner):if obj isNone:return self value = self.func(obj) obj.__dict__[self.name] = value # 缓存结果return valueclassExpensiveObject: @LazyPropertydefcomputed_value(self):print("Computing expensive value...")returnsum(i**2for i inrange(1000))obj = ExpensiveObjectprint(obj.computed_value) # 打印并计算print(obj.computed_value) # 直接返回缓存值,不打印

Log read and write operations on attributes:

Python深色版本classLogged:def__init__(self, name): self.name = namedef__set__(self, obj, value):print(f"Setting {self.name} to {value}") obj.__dict__[self.name] = valuedef__get__(self, obj, owner):if obj isNone:return selfprint(f"Getting {self.name}")return obj.__dict__.get(self.name)classBankAccount: balance = Logged('balance')acc = BankAccountacc.balance = 1000# 输出: Setting balance to 1000print(acc.balance) # 输出: Getting balance \n 1000Python深色版本classBad:def__init__(self): self.x = Typed(int) # ❌ 无效!不是类属性

一旦定义,实例字典中的同名属性将被忽略。

数据描述符优先级最高

Once a descriptor is defined, any instance dictionary entry with the same name will be ignored.

避免在 __set__ 中无限递归
不要直接赋值描述符自身属性,应使用 obj.__dict__。

Do not directly assign to the descriptor’s own attribute; instead, use obj.__dict__ to store the value.

描述符是 Python 面向对象系统中最强大、最灵活的工具之一。它不仅是 @property、@classmethod 等内置装饰器的底层实现,更是构建领域特定语言(DSL)ORM 框架(如 Django、SQLAlchemy)和配置系统的核心机制。

Descriptors are one of the most powerful and flexible tools in Python's object-oriented system. They not only form the underlying mechanism for built-in decorators like @property and @classmethod, but are also the core foundation for building:Domain-Specific Languages (DSLs)、ORM frameworks(e.g., Django, SQLAlchemy)、Configuration systems

虽然描述符的学习曲线较陡,但一旦掌握,你将:

Although the learning curve for descriptors is steep, mastering them enables you to:

深入理解 Python 属性查找机制

Deeply understand Python's attribute lookup mechanism

能够编写高度可复用的属性逻辑

Write highly reusable and modular attribute logic

具备设计复杂对象系统的能力

Design complex object systems with fine-grained control

但有了描述符,你不仅能“同意”,还能“完全掌控”。

But with descriptors, you not only consent — you gain complete control.

今天的分享就到这里了。

如果您对文章有独特的想法,

欢迎给我们留言,

让我们相约明天。

祝您今天过得开心快乐!

That's all for today's sharing.

If you have a unique idea about the article,

please leave us a message,

and let us meet tomorrow.

I wish you a nice day!

参考资料:通义千问

参考文献:Beazley, D., & Jones, B. K. (2019). Python Cookbook (3rd ed.). O'Reilly Media.

Hettinger, R. (2019). Transforming Code into Beautiful, Idiomatic Python. PyCon US.

本文由LearningYard新学苑整理发出,如有侵权请在后台留言沟通!

LearningYard新学苑

文字:song

排版:song

审核|hzy

来源:LearningYard学苑

相关推荐