Python 中的 __set_name__ 描述符协议
Python 3.6 引入的 __set_name__ 方法在描述符中有什么作用?如何利用它自动捕获属性名?
回答
小字辈
__set_name__(self, owner, name) 在类创建时自动调用,将描述符实例绑定的属性名传递给描述符。
class ValidatedAttr:
def __set_name__(self, owner, name):
self.private_name = f'_{name}'
self.public_name = name
def __get__(self, obj, objtype=None):
if obj is None:
return self
return getattr(obj, self.private_name, None)
def __set__(self, obj, value):
if not isinstance(value, str):
raise TypeError(f'{self.public_name} must be str')
setattr(obj, self.private_name, value)
class Person:
name = ValidatedAttr() # __set_name__ 自动将 'name' 传递
email = ValidatedAttr() # __set_name__ 自动将 'email' 传递
def __init__(self, name, email):
self.name = name
self.email = email
优势:
- 无需在
__init__中手动设置属性名 - 支持不同的属性使用同一个描述符类
- 内部存储使用
_attrname避免命名冲突
这在 ORM 框架(如 SQLAlchemy)、验证库中广泛使用。