我想動態地添加一個'可鎖定'功能的值。雖然這個特定的案例看起來微不足道或者比較麻煩,但我想擴展我的可鎖定混合類以適應各種不同的用例。我不想一次性鎖定價值;我希望這是足夠通用的,以控制任何數量的類屬性。動態更新python屬性setter方法
我完成後的期望是最後的斷言會通過。
我曾嘗試使用超級而不是自我。 setattr,但我收到一個錯誤,該屬性是隻讀的。這讓我懷疑我是否可以做我想做的事情。
任何幫助將不勝感激,並提前致謝!
一些代碼:
from collections import OrderedDict as OD
def lockable(func, locked=None):
def wrapper(*args, **kwds):
if locked:
val = None
else:
val = func(*args, **kwds)
return val
return wrapper
class Mixin(object):
@property
def meta(self):
attr = "__meta__"
if not hasattr(self, attr):
setattr(self, attr, OD())
return getattr(self, attr)
class LockableMixin(Mixin):
@property
def locked(self):
self.meta.setdefault("locked", False)
return self.meta.get("locked")
@locked.setter
def locked(self, value):
value = value if value in [None, True, False] else self.meta['locked']
self.meta['locked'] = value
def lock(self):
self.locked = True
def unlock(self):
self.locked = False
def is_locked(self):
return self.locked
def __init__(self):
super(LockableMixin, self).__init__()
self.__setattr__ = lockable(self.__setattr__, self.locked)
class Attribute(object):
@property
def value(self):
attr = "__value__"
if not hasattr(self, attr):
setattr(self, attr, False)
return getattr(self, attr)
@value.setter
def value(self, value):
self.__value__ = value
def __init__(self, value):
self.value = value
super(Attribute, self).__init__()
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = value
def __str__(self):
return str(self.value)
def __repr__(self):
cname = self.__class__.__name__
value = str(self.value)
return "<%s %s>" % (cname, value)
class LockableAttribute(Attribute, LockableMixin):
pass
if __name__ == "__main__":
a1 = Attribute(1)
a2 = LockableAttribute(1)
assert a2.locked is False
assert a2.value == 1
a2.lock()
assert a2.locked is True
a2.unlock()
assert a2.locked is False
a2.value = 2
assert a2.value == 2
a2.locked = True
a2.value = 3
assert a2.value == 2 # This will raise an exception, but it shouldn't.
這裏更像是一個用例的組件類:
class Component(object):
@property
def attributes(self):
attrs = {}
for field in self.__fields__:
attrs[field] = self.get(field)
return attrs
def __init__(self, **attributes):
super(Component, self).__init__()
self.__fields__ = []
for name, val in attributes.iteritems():
if name not in self.__fields__:
self.__fields__.append(name)
setattr(self, name, val)
def __setattr__(self, name, value):
if not name.startswith("__"):
if not isinstance(value, Attribute):
value = Attribute(value)
super(Component, self).__setattr__(name, value)
def __getitem__(self, name):
return getattr(self, name, None)
def get(self, name, default=None):
return getattr(self, name, default)
# Case 1: a lockable attribute
c = Component(name="Joe Schmoe", dob=LockableDateAttribute("04/12/2014"))
c.dob.lock()
c.dob.unlock()
# Case 2: a lockable component class containing arbitrary number of lockable attributes
c2 = LockableComponent(name="Jill Pill", dob=LockableDateAttribute("04/12/2014))
c2.lock() # locks all of the lockable attributes
有趣的運動:)讓我試着去了解......那麼你是否想要在一個具有任意數量屬性的類中鎖定一個屬性? – BorrajaX
總之:是的。 我想象一個組件,其中有一組屬性,我可以鎖定組件,包括其所有屬性(可能是列表,元組或集合)。我希望所有屬性都可以在一定程度上相互兼容。但有些可能是可鎖定的。有些可能會被禁用...等等。 –
等等......如果你在鎖定a2的值爲2時,爲什麼會聲明'a2.value == 2'失敗?你的意思是'assert a2.value == 3'會失敗嗎? – BorrajaX