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

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

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

还是我错过了什么?

347066 次浏览

使用列表/字典或者定义你自己的类来封装你定义的东西,但是如果你需要所有这些变量,你可以这样做:

a = b = c = d = e = g = h = i = j = True
f = False

在我看来,你处理问题的方式不对。

重写代码以使用元组或编写类来存储所有数据。

这是对@Jeff M和我的评论的阐述。

当你这样做的时候:

a, b = c, d

它与元组打包和解包一起工作。您可以分离打包和解包步骤:

_ = c, d
a, b = _

第一行创建一个名为 _的元组,它有两个元素,第一个元素的值为 c,第二个元素的值为 d。第二行将 _元组解包到变量 ab中。这打破了你的一个巨大的界限:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True, True, True, True

分成两条小线:

_ = True, True, True, True, True, False, True, True, True, True
a, b, c, d, e, f, g, h, i, j = _

它将给出与第一行完全相同的结果(如果向一个部分添加值或变量但忘记更新另一个部分,则包括相同的异常)。 然而,在这个特定的情况下,严的回答可能是最好的。

如果您有一个值列表,您仍然可以解压缩它们。你只需要先把它转换成一个元组。例如,下面将分别为 aj中的每一个分配一个0到9之间的值:

a, b, c, d, e, f, g, h, i, j = tuple(range(10))

编辑: 除了元素5(变量 f)之外,将它们全部赋值为 true 的巧妙技巧:

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

正如其他人所建议的那样,使用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>


另一种方法是将数据定义为映射到标志名称(单字符串)的标志值列表(TrueFalse) ,如果您经常使用这种模式,这种方法可能是最直观的。然后将此数据定义转换为一个倒置字典,该字典将标志名称映射到标志值。使用嵌套的列表内涵可以很简洁地完成这个任务,但是这里有一个非常可读的实现:

>>> 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 字符串是 < em > 可迭代的 ,这意味着它们可以通过值来移动。对于字符串,值是字符串中的单个字符。因此,当它们被解释为可迭代的时候,比如在 for 循环中使用它们时,['a', 'b', 'c']'abc'实际上是等价的。另一个例子是,当它们被传递给一个采用可迭代的函数(如 tuple)时。

我个人不会这样做,因为它不能直观地读取: 当我看到一个字符串时,我希望它被用作单个值而不是列表。所以我看着第一行,然后想“好吧,这里有一个真旗和一个假旗。”所以尽管有这种可能性,但我不认为这是正确的选择。从好的方面来说,它可能有助于更清楚地解释可迭代器和迭代器的概念。


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


显然,Python 2.7具有字典理解功能,这将为实现该函数提供一种非常简洁的方法。这是留给读者的练习,因为我没有安装 Python 2.7:)

您还可以组合来自通用 Itertools模块的一些函数。就像他们说的,有不止一种方法。等等,巨蟒的人不会这么说。不管怎样,在某些情况下这是真的。我猜想圭多已经给了我们词典的理解,这样就会有 一种显而易见的方式来做这件事。

当人们建议“使用列表、元组或其他数据结构”时,他们的意思是,当你有许多不同的值时,将它们分别命名为局部变量可能不是最好的方法。

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

直观地展示了如何使用字典来解决这个问题,Chris Lutz 展示了如何在分解成单独的变量之前使用 tuple 进行临时存储,但是另一个需要考虑的选项是使用 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)

当然,真正的代码可能会使用比“ DataHolder”和字母表中的字母更有意义的名称。

有什么问题吗?

如果你真的需要或者想要10个 BCD你好FJ,在某个时候,没有其他的可能性写 ,写 B,写 C... ..。

如果所有值都不相同,那么您将不得不编写示例

a = 12
b= 'sun'
c = A() #(where A is a class)
d = range(1,102,5)
e = (line in filehandler if line.rstrip())
f = 0,12358
g = True
h = random.choice
i = re.compile('^(!=  ab).+?<span>')
j = [78,89,90,0]

也就是说分别定义“变量”。

或者,使用另一种写法,不需要使用 _:

a,b,c,d,e,f,g,h,i,j =\
12,'sun',A(),range(1,102,5),\
(line for line in filehandler if line.rstrip()),\
0.12358,True,random.choice,\
re.compile('^(!=  ab).+?<span>'),[78,89,90,0]

或者

a,b,c,d,e,f,g,h,i,j =\
(12,'sun',A(),range(1,102,5),
(line for line in filehandler if line.rstrip()),
0.12358,True,random.choice,
re.compile('^(!=  ab).+?<span>'),[78,89,90,0])

.

如果它们中的一些必须具有相同的值,那么问题就在于它太长而无法写入

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True

然后你可以写:

a=b=c=d=e=g=h=i=k=j=True
f = False

.

我不明白你到底有什么问题。如果你想写代码,你必须使用书写指令和定义所需要的字符。还有呢?

我想知道你的问题是否意味着你误解了什么。

当一个人写 a = 10不创建变量的意思是“其值可以改变的内存块”。这个指令:

  • 要么触发创建类型为 integer和值为10的对象,并在当前命名空间中将名称“ a”与该对象绑定

  • 或者将名称空间中的“ a”重新分配给对象 10(因为“ a”以前绑定到另一个对象)

我这样说是因为我没有看到定义10个标识符 a、 b、 c 的实用程序。.指向虚假或真实。如果这些值在执行过程中没有变化,为什么有10个标识符?如果它们发生了变化,为什么要首先定义标识符呢?如果没有事先定义,它们将在需要时被创建

我觉得你的问题很奇怪

a, b, c, d, e, g, h, i, j = (True,)*9
f = False

我喜欢投票最多的答案,但是,它与列表有问题,如图所示。

  >> a, b = ([0]*5,)*2
>> print b
[0, 0, 0, 0, 0]
>> a[0] = 1
>> print b
[1, 0, 0, 0, 0]

这在 (在此)中有详细的讨论,但要点是 ab是同一个对象,a is b返回 True(id(a) == id(b)也是如此)。因此,如果更改索引,则是更改 ab的索引,因为它们是链接的。要解决这个问题,你可以做 (资料来源)

>> a, b = ([0]*5 for i in range(2))
>> print b
[0, 0, 0, 0, 0]
>> a[0] = 1
>> print b
[0, 0, 0, 0, 0]

然后,这可以作为顶级答案的一个变体,它具有“理想的”直观结果

>> a, b, c, d, e, g, h, i = (True for i in range(9))
>> f = (False for i in range(1)) #to be pedantic

JavaScript一样,在 pythona = 1; b = "Hello World"; c += 3中也可以在一行中使用多个语句

在你的情况下,我会使用 YAML。

这是处理多个参数的优雅而专业的标准。 这些值是从一个单独的文件加载的。 你可以在这个链接中看到一些信息:

Https://keleshev.com/yaml-quick-introduction

但是谷歌它更容易,因为它是一个标准,有数以百计的信息关于它,你可以找到什么最适合你的理解。;)

最好的问候。