[英]How can I override property setting for a dict-like object?
我正在編寫C綁定,並且要包裝的C結構具有一些字符串索引的屬性值。
我想將這些作為python中的dict公開。
到目前為止,我有一個函數get_properties
,該函數以單個字典形式返回對象的所有屬性。 我使用property
函數將其包裝在類定義中,以便可以將其作為類屬性進行訪問:
(在類中定義)
class MyClass:
def get_properties(self):
...
properties = property(get_properties)
(例)
>>> print myobj.properties
{'test': 5, 'test2': 'string'}
現在,我想以類似dict的方式來設置它們。 我有一個名為set_property
的C函數的包裝函數,該函數具有字符串鍵和幾種類型的值。
我嘗試從類property
使用set_properties
:
class MyClass:
def get_properties(self):
...
def set_property(self, key, value):
...
def set_properties(self, props):
[self.set_property(k, props[k]) for k in props]
properties = property(get_properties, set_properties)
如下所示:
>>> myobj.properties = {"test3": 6}
>>> print myobj.properties
{'test': 5, 'test2': 'string', 'test3': 6}
但是,您可以看到,這並不完全是預期的行為。 我更喜歡的是:
>>> myobj.properties['test3'] = 6
我嘗試為properties
添加__setitem__
的定義:
class MyClass:
...
properties = property(get_properties)
properties.__setitem__ = set_property
但這讓我
AttributeError: 'property' object has no attribute '__setitem__'
我試圖使屬性成為dict,並簡單地覆蓋__setitem__
和__getitem__
但是它沒有它。
知道這樣做的正確方法是什么嗎? 我可以使類property
表現得像字典嗎?
謝謝。
好的,Mike的回答給了我解決這個問題的想法,方法是使用擴展的dict類從屬性的getter返回,在該類中,我根據上下文覆蓋了__setitem__
:
class MyClass(object):
def get_properties():
... (call C function and convert to dict)
def set_property():
... (call C function)
def propgetter(self):
context = self
props = self.get_properties()
class propsetter(dict):
__getitem__ = props.__getitem__
def __setitem__(self, key, value):
props[key] = value
context.set_property(key, value)
return propsetter(self.get_properties())
properties = property(propgetter)
看起來像我想要的那樣工作。
您定義屬性的方式是只讀的。 但是,屬性裝飾器實際上可以選擇使用set和get函數:
class MyClass(object):
def __init__(self):
self.d = {"hello":None}
def __repr__(self):
return "%s"%(self.d,)
def get(self):
return self.d
def set(self, value):
self.d = value
x = property(get, set)
通過為內部字典定義setter,您現在可以在其上設置鍵:
>>> c = MyClass()
>>> c.x
{'hello': None}
>>> c.x["hello"] = "world"
>>> c.x
{'hello': 'world'}
>>> c.x = {"key":"value"}
>>> c.x
{'key': 'value'}
另外,如果您使用的是Python(2.6+)的最新版本,則可以使用如下裝飾器來編寫這種更好的方法:
class MyClass():
def __init__(self):
self.d = {"hello":None}
def __repr__(self):
return "%s"%(self.d,)
@property
def x(self):
return self.d
@x.setter
def set(self, value):
self.d = value
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.