我的问题很简单,我有一个包含属性路径的字符串,我想通过字符串更改该属性。
str = "someClass.property"
data = 123
'''
I don't know what str contains, as it is created by a user
I know that I could do this, but it smells like bad practice,
in PHP it's a criminal offence
'''
exec(str + " = data" )
如何在不触及exec()
的情况下实现上述操作?
答案 0 :(得分:3)
您可以使用setattr
:
setattr(someClass, property, data)
请注意,如果没有任何用户验证,这仍然很危险,因为您的用户可能会更改他们无法修改的现有属性的定义。
更安全的替代方法是使用dict
作为键值存储,并将用户定义的属性放在那里。
答案 1 :(得分:0)
首先,您要在类或实例上设置属性吗?通常,最好的方法是使用注册表来注册要更改的对象(类或实例)。这可以是一个简单的字典:
registry = {}
然后显式注册您想要被用户修改的对象,例如
class Foo(object):
pass
f1 = Foo()
f2 = Foo()
registry['Foo'] = Foo
registry['f1'] = f1
registry['f2'] = f2
对于一般的类,您可以使用<<class>>.__name__
将其封装得更多一些。
查找很容易,对于任何不应该变化的东西都会很好地失败:
objectname, propertyname = str.split('.', 1)
o = registry[objectname]
最后,可以使用setattr:
设置属性setattr(o, propertyname, data)
或者通过定义可以实际检查属性的显式设置行为来更多OO-ish,例如
class Settable(object):
allowed = ('foo', 'bar')
def set(self, prop, val):
if prop not in self.allowed:
raise KeyError, prop
setattr(self, prop, val)
并从这个类派生而来:
class Foo(Settable):
allowed = Settable.allowed + ('blah',)
registry[objectname].set(propertyname, data)