我正在为单个神经元编程模拟。因此我必须处理很多参数。现在的想法是我有两个类,一个用于SingleParameter,一个用于参数集合。我使用property()来轻松访问参数值并使代码更具可读性。这适用于sinlge参数,但我不知道如何为集合实现它,因为我想在SingleParameter之后命名Collection中的属性。这是一个例子:
class SingleParameter(object):
def __init__(self, name, default_value=0, unit='not specified'):
self.name = name
self.default_value = default_value
self.unit = unit
self.set(default_value)
def get(self):
return self._v
def set(self, value):
self._v = value
v = property(fget=get, fset=set, doc='value of parameter')
par1 = SingleParameter(name='par1', default_value=10, unit='mV')
par2 = SingleParameter(name='par2', default_value=20, unit='mA')
# par1 and par2 I can access perfectly via 'p1.v = ...'
# or get its value with 'p1.v'
class Collection(object):
def __init__(self):
self.dict = {}
def __getitem__(self, name):
return self.dict[name] # get the whole object
# to get the value instead:
# return self.dict[name].v
def add(self, parameter):
self.dict[parameter.name] = parameter
# now comes the part that I don't know how to implement with property():
# It shoule be something like
# self.__dict__[parameter.name] = property(...) ?
col = Collection()
col.add(par1)
col.add(par2)
col['par1'] # gives the whole object
# Now here is what I would like to get:
# col.par1 -> should result like col['par1'].v
# col.par1 = 5 -> should result like col['par1'].v = 5
我理解属性()的其他问题:
答案 0 :(得分:10)
查看内置函数getattr
和setattr
。你可能会更开心。
答案 1 :(得分:7)
对两个类使用相同的get / set函数会强制您使用参数列表进行丑陋的黑客攻击。非常粗略,我就是这样做的:
在Class SingleParameter中,像往常一样定义get和set:
def get(self):
return self._s
def set(self, value):
self._s = value
在类Collection中,在创建属性之前无法知道这些信息,所以你要定义metaset / metaget函数,稍后再使用lambda函数对它们进行详细说明:
def metaget(self, par):
return par.s
def metaset(self, value, par):
par.s = value
def add(self, par):
self[par.name] = par
setattr(Collection, par.name,
property(
fget=lambda x : Collection.metaget(x, par),
fset=lambda x, y : Collection.metaset(x,y, par))
答案 2 :(得分:5)
属性用于动态评估属性或使其成为只读属性。您需要的是自定义属性访问。 __getattr__
和__setattr__
做得非常好,如果__getattribute__
还不够,还有__getattr__
。
有关详细信息,请参阅Python docs on customizing attribute access。
答案 3 :(得分:3)
你看过traits package了吗?看来你正在用你的参数类重新发明轮子。特征还具有可能对您的应用类型有用的其他功能(我非常熟悉一个在神经模拟中愉快地使用特征的人)。
答案 4 :(得分:2)
现在我用set- / getattr实现了一个解决方案:
class Collection(object):
...
def __setattr__(self, name, value):
if 'dict' in self.__dict__:
if name in self.dict:
self[name].v = value
else:
self.__dict__[name] = value
def __getattr__(self, name):
return self[name].v
有一件事我不太喜欢:属性不在__dict__中。如果我在那里也有它,我会得到一个价值的副本 - 这可能是危险的......
答案 5 :(得分:0)
最后,我成功使用property()实现了这些类。非常感谢您的建议。我花了很多时间来解决它 - 但我可以向你保证,这个练习可以帮助你理解更好的蟒蛇OOP。
我也使用__getattr__和__setattr__实现了它,但仍然不知道属性解决方案的优点和缺点。但这似乎值得另一个问题。物业解决方案似乎已经放弃了。
所以这是代码:
class SingleParameter(object):
def __init__(self, name, default_value=0, unit='not specified'):
self.name = name
self.default_value = default_value
self.unit = unit
self.set(default_value)
def get(*args):
self = args[0]
print "get(): "
print args
return self._v
def set(*args):
print "set(): "
print args
self = args[0]
value = args[-1]
self._v = value
v = property(fget=get, fset=set, doc='value of parameter')
class Collection(dict):
# inheriting from dict saves the methods: __getitem__ and __init__
def add(self, par):
self[par.name] = par
# Now here comes the tricky part.
# (Note: this property call the get() and set() methods with one
# more argument than the property of SingleParameter)
setattr(Collection, par.name,
property(fget=par.get, fset=par.set))
# Applying the classes:
par1 = SingleParameter(name='par1', default_value=10, unit='mV')
par2 = SingleParameter(name='par2', default_value=20, unit='mA')
col = Collection()
col.add(par1)
col.add(par2)
# Setting parameter values:
par1.v = 13
col.par1 = 14
# Getting parameter values:
par1.v
col.par1
# checking identity:
par1.v is col.par1
# to access the whole object:
col['par1']
我是新手,我不知道如何继续前进: 如何处理后续问题(像这样):
我理解属性()的其他问题:
答案 6 :(得分:0)
我有一个类似的东西,但我在集合对象中做了以下事情:
setattr(self,par.name,par.v)