更优雅地同时声明多个变量的方法
如果我想“同时”声明多个变量,我会这样做:
a, b = True, False
但是如果我需要声明更多的变量,这样写就显得越来越不优雅了:
a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True
有没有更好、更优雅或者更方便的方法来做到这一点呢?
这可能是个很基础的问题,但如果我用列表或元组来存储这些变量,我该怎么做才能让它们有用呢?因为:
aList = [a,b]
这样写是不合法的,我必须这样做:
a, b = True, True
或者我漏掉了什么吗?
10 个回答
可以使用列表或字典,或者自己定义一个类来把你要定义的东西装起来。不过,如果你确实需要用到所有那些变量,你可以这样做:
a = b = c = d = e = g = h = i = j = True
f = False
这段代码的意思是……
首先,它定义了一些变量,这些变量用来存储信息。接下来,代码会执行一些操作,比如计算、判断条件等等。最后,代码会输出结果,让我们看到运行的效果。
如果你对某些部分不太明白,可以想象成在做数学题,先设定好数字,然后一步一步地算出答案。每一行代码就像是一个步骤,帮助我们完成整个过程。
总之,这段代码的目的是为了实现某个功能,具体的实现方式可能会有点复杂,但只要理解了每一步的作用,就能更好地掌握它。
a, b, c, d, e, g, h, i, j = (True,)*9
f = False
正如其他人所提到的,使用10个不同的布尔值局部变量来写你的程序,可能不是最好的方法(尤其是它们的名字只有一个字母 :)
根据你要做的事情,使用字典可能更合适。例如,如果你想为一组单字母的标志设置布尔预设值,你可以这样做:
>>> flags = dict.fromkeys(["a", "b", "c"], True)
>>> flags.update(dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}
如果你愿意,也可以用一个赋值语句来完成:
>>> flags = dict(dict.fromkeys(["a", "b", "c"], True),
... **dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}
这里的 dict
的第二个参数并不是专门为这个设计的:它实际上是为了让你可以用像 d=False
这样的关键字参数来覆盖字典中的单个元素。上面的代码将 **
后面的表达式展开成一组 关键字参数,这些参数会传递给被调用的函数。这绝对是创建字典的一种可靠方法,大家似乎也能接受这种写法,但我怀疑有些人可能会觉得这不够“Python风格”。</disclaimer>
还有一种方法,如果你经常使用这种模式,可能会更直观,那就是将你的数据定义为一个标志值(True
、False
)的列表,并与标志名称(单字符字符串)对应。然后你可以将这个数据定义转换成一个反向字典,映射标志名称到标志值。这可以通过嵌套列表推导式简洁地完成,但这里有一个非常易读的实现:
>>> def invert_dict(inverted_dict):
... elements = inverted_dict.iteritems()
... for flag_value, flag_names in elements:
... for flag_name in flag_names:
... yield flag_name, flag_value
...
>>> flags = {True: ["a", "b", "c"], False: ["d", "e"]}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}
函数 invert_dict
是一个 生成器函数。它会 生成 或 返回 — 意思是它会 重复返回 键值对。这些键值对是初始 flags
字典中两个元素内容的反向。它们被传入 dict
构造函数。在这种情况下,dict
构造函数的工作方式与上面不同,因为它接收的是一个 迭代器,而不是字典作为参数。
根据 @Chris Lutz 的评论:如果你真的会使用单字符的值,你实际上可以这样做:
>>> flags = {True: 'abc', False: 'de'}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}
这样做是可行的,因为Python字符串是 可迭代的,这意味着它们可以逐个值地遍历。在字符串的情况下,值就是字符串中的每个字符。因此,当它们被解释为可迭代对象时,比如在这个例子中使用在for循环中, ['a', 'b', 'c']
和 'abc'
实际上是等价的。另一个例子是当它们被传递给一个接受可迭代对象的函数,比如 tuple
。
我个人不会这样做,因为这样看起来不太直观:当我看到一个字符串时,我期待它作为一个单一的值,而不是作为一个列表。所以我看到第一行时会想,“好吧,这里有一个True标志和一个False标志。”所以虽然这是一个可能的做法,但我认为这不是最佳选择。不过,从好的一面来看,这可能有助于更清楚地解释可迭代对象和迭代器的概念。
将函数 invert_dict
定义为实际返回一个字典也不是个坏主意;我主要没有这样做,因为这并不真正有助于解释这个程序是如何工作的。
显然,Python 2.7 有字典推导式,这将使得实现这个函数的方式非常简洁。这留给读者作为练习,因为我没有安装Python 2.7 :)
你还可以结合一些来自功能强大的 itertools 模块的函数。正如他们所说的, 有很多种方法可以做到这一点。等等,Python的人并不这样说。不过,在某些情况下,这确实是对的。我猜Guido给我们提供了字典推导式,以便有 一种明显的方法 来做到这一点。