9.21 ����的属性方法¶
问题¶
ä½ åœ¨ç±»ä¸éœ€è¦�é‡�å¤�的定义一些执行相å�Œé€»è¾‘çš„å±žæ€§æ–¹æ³•ï¼Œæ¯”å¦‚è¿›è¡Œç±»åž‹æ£€æŸ¥ï¼Œæ€Žæ ·åŽ»ç®€åŒ–è¿™äº›é‡�å¤�代ç �呢?
解决方案¶
考虑下一个简�的类,它的属性由属性方法包装:
class Person:
def __init__(self, name ,age):
self.name = name
self.age = age
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not isinstance(value, str):
raise TypeError('name must be a string')
self._name = value
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if not isinstance(value, int):
raise TypeError('age must be an int')
self._age = value
å�¯ä»¥çœ‹åˆ°ï¼Œä¸ºäº†å®žçŽ°å±žæ€§å€¼çš„ç±»åž‹æ£€æŸ¥æˆ‘ä»¬å†™äº†å¾ˆå¤šçš„é‡�å¤�代ç �。 å�ªè¦�ä½ ä»¥å�Žçœ‹åˆ°ç±»ä¼¼è¿™æ ·çš„代ç �ï¼Œä½ éƒ½åº”è¯¥æƒ³åŠžæ³•åŽ»ç®€åŒ–å®ƒã€‚ 一个å�¯è¡Œçš„æ–¹æ³•是创建一个函数用æ�¥å®šä¹‰å±žæ€§å¹¶è¿”回它。例如:
def typed_property(name, expected_type):
storage_name = '_' + name
@property
def prop(self):
return getattr(self, storage_name)
@prop.setter
def prop(self, value):
if not isinstance(value, expected_type):
raise TypeError('{} must be a {}'.format(name, expected_type))
setattr(self, storage_name, value)
return prop
# Example use
class Person:
name = typed_property('name', str)
age = typed_property('age', int)
def __init__(self, name, age):
self.name = name
self.age = age
讨论¶
本节我们演示内部函数或者é—包的一个é‡�è¦�特性,它们很åƒ�一个å®�。例å�ä¸çš„函数 typed_property()
看上去有点难ç�†è§£ï¼Œå…¶å®žå®ƒæ‰€å�šçš„ä»…ä»…å°±æ˜¯ä¸ºä½ ç”Ÿæˆ�属性并返回这个属性对象。
å› æ¤ï¼Œå½“在一个类ä¸ä½¿ç”¨å®ƒçš„æ—¶å€™ï¼Œæ•ˆæžœè·Ÿå°†å®ƒé‡Œé�¢çš„代ç �放到类定义ä¸åŽ»æ˜¯ä¸€æ ·çš„ã€‚
尽管属性的 getter 和 setter 方法访问了本地��如 name , expected_type
以å�Š storate_name ,这个很æ£å¸¸ï¼Œè¿™äº›å�˜é‡�的值会ä¿�å˜åœ¨é—包当ä¸ã€‚
我们还å�¯ä»¥ä½¿ç”¨ functools.partial() æ�¥ç¨�ç¨�改å�˜ä¸‹è¿™ä¸ªä¾‹å�ï¼Œå¾ˆæœ‰è¶£ã€‚ä¾‹å¦‚ï¼Œä½ å�¯ä»¥åƒ�下é�¢è¿™æ ·ï¼š
from functools import partial
String = partial(typed_property, expected_type=str)
Integer = partial(typed_property, expected_type=int)
# Example:
class Person:
name = String('name')
age = Integer('age')
def __init__(self, name, age):
self.name = name
self.age = age
å…¶å®žä½ å�¯ä»¥å�‘现,这里的代ç �è·Ÿ8.13å°�节ä¸çš„类型系统æ��述器代ç �有些相似。