将一组变量分配给类对象,通常是这样的:
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
容纳的None
和len(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
添加一个方便的方法。