更优雅的方式同时声明多个变量

Tru*_*ufa 129 python variables declaration

要在"同一时间"声明多个变量,我会这样做:

a, b = True, False
Run Code Online (Sandbox Code Playgroud)

但是,如果我必须声明更多的变量,它变得越来越不优雅:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True
Run Code Online (Sandbox Code Playgroud)

有没有更好/优雅/方便的方法来做到这一点?

提前致谢!

编辑:

这必须是非常基本的,但是如果我使用列表或元组来存储变量,我将如何处理以便我有所帮助,因为:

aList = [a,b]
Run Code Online (Sandbox Code Playgroud)

无效,我必须这样做:

a, b = True, True
Run Code Online (Sandbox Code Playgroud)

或者我错过了什么?

小智 214

a, b, c, d, e, g, h, i, j = (True,)*9
f = False
Run Code Online (Sandbox Code Playgroud)

  • 优雅的技巧,但要注意在列表等可变元素上使用它.例如,`a,b,c =([],)*3`不会创建3个列表实例,但会使`a`,`b`和`c`指向同一个实例. (33认同)
  • @Imray Trailing逗号符号`(d,)`创建一个单项元组,这是一个序列类型.[序列类型](https://docs.python.org/2/library/stdtypes.html#sequence-types-str-unicode-list-tuple-bytearray-buffer-xrange)支持加法和乘法等操作. (20认同)
  • 我不知道我浪费/花费的时间试图让我的python代码超级pythonic? (4认同)
  • @Zac正确地使用`a,b,c =([[i]在range(3)中)]。[来源](/sf/ask/168185251/)。为了保持一致性,您还可以对此答案使用一个变体,即,'a,b,c,d,e,g,h,i,j =(真i在range(9)中)'f = (范围(1)中的i为假)`。 (2认同)

yan*_*yan 48

使用列表/字典或定义您自己的类来封装您正在定义的内容,但如果您需要所有这些变量,您可以执行以下操作:

a = b = c = d = e = g = h = i = j = True
f = False
Run Code Online (Sandbox Code Playgroud)

  • 为了解释为什么这是一种危险模式(尽管是工作示例),请阅读[Notorious BIG](http://stackoverflow.com/a/16349356/134610) (5认同)

int*_*ted 48

正如其他人所建议的那样,使用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}
Run Code Online (Sandbox Code Playgroud)

如果您愿意,也可以使用单个赋值语句执行此操作:

>>> 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}
Run Code Online (Sandbox Code Playgroud)

第二个参数dict并不是完全为此设计的:它实际上是允许您使用关键字参数覆盖字典的各个元素d=False.上面的代码将表达式的结果**放入一组传递给被调用函数的关键字参数中.这当然是创建字典的可靠方式,人们似乎至少接受了这个成语,但我怀疑有些人可能认为它是Unpythonic. </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}
Run Code Online (Sandbox Code Playgroud)

该功能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}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为Python字符串是可迭代的,这意味着它们可以通过值逐行移动.对于字符串,值是字符串中的单个字符.因此,当它们被解释为迭代时,就像在这种情况下它们被用于for循环一样,['a', 'b', 'c']并且'abc'实际上是等价的.另一个例子是当它们被传递给一个可迭代的函数时,比如tuple.

我个人不会这样做,因为它不直观地阅读:当我看到一个字符串时,我希望它被用作单个值而不是列表.所以我看第一行并想"好的,所以有一个真旗和一个假旗." 所以虽然这是一种可能性,但我认为这不是可行的方法.从好的方面来说,可以更清楚地解释迭代和迭代器的概念.


定义函数invert_dict使其实际返回字典也不是一个坏主意; 我大多只是不这样做,因为它没有真正帮助解释例程如何工作.


显然,Python 2.7具有字典理解,这将使得实现该功能的方式非常简洁.这是留给读者的练习,因为我没有安装Python 2.7 :)

您还可以组合来自多功能itertools模块的一些功能.正如他们所说,有不止一种方法可以做到这一点.等等,Python的人不这么说.嗯,在某些情况下无论如何都是如此.我猜想Guido已经给了我们字典理解,以便有一个明显的方法来做到这一点.

  • @intuited我对你的答案感到惊讶:你定义了另一个问题,而不是OP的问题,你很乐意对这个问题做一个很长的答案.他不想在字典中关联字符串和值,他想创建具有标识符和每个字符串值的对象. (5认同)
  • @eyquem:答案很长很糟糕?医师,治愈你自己! (5认同)
  • 这不回答这个问题,而且它是光顾的.请参阅以下答案 (5认同)
  • 请注意, `['a', 'b', 'c']` 可以缩写为 `list('abc')`,这启发了 `def true_values(trues, falses): d = dict.from_keys(list(trues) ), 真的); d.update(dict.from_keys(列表(falses), False)); 返回 d` 用作 `values = true_values("abc", "de")` (2认同)

Chr*_*utz 9

这是关于@ Jeff M和我的评论的详细说明.

当你这样做:

a, b = c, d
Run Code Online (Sandbox Code Playgroud)

它适用于元组打包和拆包.您可以分开包装和拆包步骤:

_ = c, d
a, b = _
Run Code Online (Sandbox Code Playgroud)

第一行创建一个名为的元组_,它有两个元素,第一个元素值为,c第二个元素值为d.第二行将_元组解压缩到变量ab.这打破了你的一条巨大的路线:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True, True, True, True
Run Code Online (Sandbox Code Playgroud)

分成两条较小的线:

_ = True, True, True, True, True, False, True, True, True, True
a, b, c, d, e, f, g, h, i, j = _
Run Code Online (Sandbox Code Playgroud)

它将为您提供与第一行完全相同的结果(如果您将值或变量添加到一个部分但忘记更新另一个部分,则包括相同的异常).但是,在这个具体案例中,颜的答案可能是最好的.

如果您有值列表,仍可以解压缩它们.你只需要先将其转换为元组.例如,以下内容将分别为每个athrough 分配0到9之间的值j:

a, b, c, d, e, f, g, h, i, j = tuple(range(10))
Run Code Online (Sandbox Code Playgroud)

编辑:除了元素5(变量f)之外,将所有这些分配为true的巧妙技巧:

a, b, c, d, e, f, g, h, i, j = tuple(x != 5 for x in range(10))
Run Code Online (Sandbox Code Playgroud)


nco*_*lan 5

当人们建议"使用列表或元组或其他数据结构"时,他们所说的是,当你有很多不同的值时,将它们全部分别命名为局部变量可能不是最好的方法做事.

相反,您可能希望将它们聚集在一起,形成一个可以存储在单个局部变量中的更大的数据结构.

直觉显示了你如何使用字典,Chris Lutz展示了如何在解包成单独的变量之前使用元组进行临时存储,但另一个需要考虑的选择是使用collections.namedtuple更永久地捆绑值.

所以你可以这样做:

# Define the attributes of our named tuple
from collections import namedtuple
DataHolder = namedtuple("DataHolder", "a b c d e f g")

# Store our data
data = DataHolder(True, True, True, True, True, False, True)

# Retrieve our data
print(data)
print(data.a, data.f)
Run Code Online (Sandbox Code Playgroud)

当然,真正的代码希望使用比"DataHolder"和字母表字母更有意义的名称.