2011-02-28 68 views
1

我正在寫一個C綁定,並且我要包裝的C結構有一些字符串索引的屬性值。如何覆蓋字典對象的屬性設置?

我想揭露這些作爲Python中的字典。

到目前爲止,我有一個函數get_properties,它將所有對象的屬性作爲單個字典返回。我包裹此使用的類定義中的property功能,這樣我可以作爲一類屬性訪問它:

(在類定義)

class MyClass: 
    def get_properties(self): 
     ... 
    properties = property(get_properties) 

(實施例)

>>> print myobj.properties 
{'test': 5, 'test2': 'string'} 

現在,我想用類似字典的方式來處理它們。我有一個名爲set_property的C函數的包裝函數,該函數接受一個字符串鍵和幾個類型的值。

我嘗試使用set_properties從我property類:

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 

我嘗試添加一個定義__setitem__properties

class MyClass: 
    ... 
    properties = property(get_properties) 
    properties.__setitem__ = set_property 

但是,這讓我,

AttributeError: 'property' object has no attribute '__setitem__' 

我試圖使財產一個字典,並簡單地覆蓋__setitem____getitem__但它不會有它。

任何想法什麼是正確的方法來做到這一點?我可以讓property類似字典嗎?

謝謝。

回答

2

好吧,小李的回答給了我這個想法從屬性的getter返回與擴展dict類,在我重寫__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) 

似乎按我的意願工作。

1

您定義屬性的方式爲只讀。然而,物業裝飾實際需要任意設置和獲取功能:

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) 

通過定義爲內部字典中的二傳手,你現在可以設置它的鍵:

>>> 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 
+0

恐怕在你的例子中,setter永遠不會被調用。你通過getter使用底層字典表示法。我正在嘗試_intercept_類似於__setitem__'的調用,並將其替換爲我的C庫的表示形式。 – Steve 2011-03-01 00:55:57

+0

在你的問題中你說過:「但是,你可以看到它不完全是預期行爲,我更喜歡的是: >>> myobj.properties ['test3'] = 6」。通過添加一個示例工作的setter是我唯一的觀點。無論如何,所以你真的在尋找如何在C Python API中繼承dict的子類,或者如何實現內建類型的dict接口?你現在如何包裝你的C數據結構,並將它提供給Python? – stderr 2011-03-01 01:22:47

+0

是的,這就是我想要的。但是我希望myobj.properties ['test3']調用'__setitem__'的_my_版本,這不是你的例子。 – Steve 2011-03-01 01:24:36