我正在编写一个C绑定,而我正在包装的C结构有一些字符串索引的属性值。
我想在python中将这些作为dict公开。
到目前为止,我有一个函数get_properties
,它将所有对象的属性作为单个dict返回。我使用类定义中的property
函数将其包装,以便我可以作为类属性访问它:
(在课堂定义中)
class MyClass:
def get_properties(self):
...
properties = property(get_properties)
(实施例)
>>> print myobj.properties
{'test': 5, 'test2': 'string'}
现在,我想以类似dict的方式设置它们。我有一个名为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__'
我尝试将属性设为dict,只是覆盖__setitem__
和__getitem__
,但它不会拥有它。
知道正确的方法是什么?我可以让班级property
表现得像字典吗?
感谢。
答案 0 :(得分:2)
好的,Mike的回答给了我一个想法,通过从属性的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 :(得分: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)
通过为内部词典定义一个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