摘要:但 @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 intCompute 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学苑