Python描述符协议实战:构建智能属性管理系统
一、技术优势
描述符使属性管理代码减少70%,验证逻辑复用率提升300%
class Person:
age = PositiveInteger() # 描述符实例
name = NonEmptyString()
def __init__(self, name, age):
self.name = name # 自动触发描述符验证
self.age = age
二、核心实现
1. 基础描述符类
class Validator:
def __set_name__(self, owner, name):
self.private_name = f'_{name}'
def __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)
def validate(self, value):
raise NotImplementedError
2. 类型检查描述符
class Typed(Validator):
def __init__(self, type_):
self.type = type_
def validate(self, value):
if not isinstance(value, self.type):
raise TypeError(f'Expected {self.type}')
# 使用示例
class Product:
price = Typed(float)
name = Typed(str)
三、高级应用
1. 范围验证描述符
class Bounded(Validator):
def __init__(self, min=None, max=None):
self.min = min
self.max = max
def validate(self, value):
if self.min is not None and value = {self.min}')
if self.max is not None and value > self.max:
raise ValueError(f'Value must be <= {self.max}')
# 使用示例
class Temperature:
celsius = Bounded(-273.15) # 绝对零度
2. 惰性计算属性
class LazyProperty:
def __init__(self, func):
self.func = func
def __get__(self, obj, objtype=None):
if obj is None:
return self
value = self.func(obj)
setattr(obj, self.func.__name__, value)
return value
# 使用示例
class Circle:
def __init__(self, radius):
self.radius = radius
@LazyProperty
def area(self):
print('Calculating area...')
return 3.14 * self.radius ** 2
四、完整案例
用户账户系统
class Account:
username = NonEmptyString(max_length=20)
password = PasswordStrength(min_length=8)
balance = Bounded(min=0)
created_at = ReadOnlyDateTime()
def __init__(self, username, password):
self.username = username
self.password = password
self.balance = 0
self.created_at = datetime.now()
# 密码强度描述符
class PasswordStrength(Validator):
def __init__(self, min_length=6):
self.min_length = min_length
def validate(self, value):
if len(value) < self.min_length:
raise ValueError(f'Password too short')
if value.isdigit() or value.isalpha():
raise ValueError('Password too simple')
// 仅用于展示交互效果
function runDemo() {
alert(‘尝试在Python中运行: nnaccount = Account(“user”, “weak”)n# 将抛出密码强度异常’);
}