将变量分配给类对象属性的更方便的方法



将一组变量分配给类对象,通常是这样的:

player.x = 1
player.y = 10
player.name = 'John'

因为列表和元组允许您执行

a,b,c = (1,10,'John')

所以这是

player.x,player.y,player.name = (1,10,'John')

或者这个

player.x,player.y,player.name = 1,10,'John'

我想更改player的属性,我需要键入太多的player。这样做是不是更懒惰?

这样的东西怎么样:

def set_properties(instance, properties):
    for property in properties:
        setattr(instance, property, properties[property])

既然我们谈论的是一个懒惰的程序员,你可以将函数重写为:

def set_properties(instance, properties):
    for key,val in properties.iteritems():
        setattr(instance, key, val)

上面的代码稍微短一点,但对于大型字典也应该运行得更快,因为它在循环之前被解压缩过一次。与第一个版本相比,在第一个版本中,每次迭代都会调用属性字典。

用法:

set_properties(player, {'x': 1, 'y': 10, 'name': 'John'})
player.__dict__.update({'x':12,'y':24,'name':'Billy'})

不短,但使用字典在更多情况下比您提供的直接示例更方便。

使用zip()player.__dict__:

In [14]: class player:
   ....:     pass
   ....: 
In [15]: for prop,value in zip(("x","y","name"),(1,10,"john")):
    player.__dict__[prop]=value
   ....:     
   ....:     
In [18]: player.__dict__
Out[18]: {'__doc__': None, '__module__': '__main__', 'name': 'john', 'x': 1, 'y': 10}

这里有另一种方法,但和所有其他方法一样,它的可读性不如最初的方法:

from functools import partial
map(partial(setattr, player), ("x", "y", "name"), (1, 10, 'John'))

如果您在代码中的多个位置设置了相同的一组或多组属性,那么为每个这样的集合添加一个命名良好的方法可能是更好的选择?

class Player(object):
    # [...]
    def set_stats(self, x, y, name):
        self.x = x
        self.y = y
        self.name = name

然后,您可以使用简短且可读性强的代码设置这些属性:

player.set_stats(1, 10, "John")

基本循环可以工作:

for (k,v) in zip(attribute_names, attributes_values):
    setattr(player, k, v)

当然,你可以起诉一些列表理解,比如:

trash = [setattr(player, k, v) for (k,v) in zip(attribute_names, attributes_values)]

但它并没有真正改善任何东西(你的trash容纳的Nonelen(attribute_names)一样多…

您可以使用一种方法将对属性的更改打包在一起,您可能会发现这些更改总是一起发生,如def edit(self, **kwargs)或只是位置参数,并在其中的播放器类上分配self.property = kwargs.get(propertyName, default)。您还可以在类上创建一个属性,该属性执行您在示例中使用的类型的元组赋值。

我不能100%确定,但在我看来,在这种情况下,使用namedtuple将是一种更好的方法:需要注意的是,只应存在已知字段(即,不能动态添加/删除),并且该类实际上只不过是一个对字段具有属性样式访问权限的记录。

from collections import namedtuple
Player = namedtuple('Player', 'x y name')
player = Player._make([1, 3, 'Bob'])
print player
# Player(x=1, y=3, name='Bob')
player = player._replace(name='Jim', x=13)
print player
# Player(x=13, y=3, name='Jim')

否则,我个人会为您的Player class添加一个方便的方法。

最新更新