2010-11-08 92 views
1

我的问题很简单,我有一个字符串包含一个属性的路径,我想通过字符串更改该属性。如何动态更改属性?

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()

回答

3

你可以使用setattr

setattr(someClass, property, data) 

注意,这仍然是危险的,如果没有任何用户验证您的用户可能会改变现有的定义做属性,他们不应该能够修改。

一个更安全的替代方法是使用dict作为键值存储并将用户定义的属性放在那里。

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十岁上下的定义可以真正检查属性的显式设置行为,例如

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)