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

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

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

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

还是我想念什么?

To declare multiple variables at the “same time” I would do:

a, b = True, False

But if I had to declare much more variables, it turns less and less elegant:

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

Is there a better / elegant / convenient way to do this?

This must be very basic, but if I do used a list or a tuple for storing the variables, how would I have to approach so that I would be helpful since:

aList = [a,b]

Is not valid, I would have to do:

a, b = True, True

Or what am I missing?


回答 0

正如其他人所建议的那样,不太可能将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字符串是可迭代的,这意味着它们可以逐值移动。对于字符串,值是字符串中的各个字符。因此,当它们被解释为可迭代时,例如在这种情况下,它们在for循环中使用,['a', 'b', 'c']并且'abc'等效。另一个示例是将它们传递给需要迭代的函数时,例如tuple

我个人不会这样做,因为它不能直观地理解:当我看到一个字符串时,我希望它可以用作单个值而不是列表。因此,我看第一行并认为:“好的,所以有一个True标志和一个False标志。” 因此,尽管有可能,但我不认为这是可行的方法。从好的方面来说,这可能有助于更清楚地解释可迭代和迭代器的概念。


定义函数invert_dict以使其实际上返回字典也不是坏主意。我大多只是不这样做,因为它并不能真正帮助解释例程的工作原理。


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

您还可以结合功能广泛的itertools模块中的某些功能。正如他们所说的,有不止一种方法可以做到。等等,Python人士不这么说。好吧,在某些情况下还是如此。我猜想Guido已经给了我们字典理解能力,所以会有一种明显的方式来做到这一点。

As others have suggested, it’s unlikely that using 10 different local variables with Boolean values is the best way to write your routine (especially if they really have one-letter names :)

Depending on what you’re doing, it may make sense to use a dictionary instead. For example, if you want to set up Boolean preset values for a set of one-letter flags, you could do this:

>>> 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}

If you prefer, you can also do it with a single assignment statement:

>>> 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}

The second parameter to dict isn’t entirely designed for this: it’s really meant to allow you to override individual elements of the dictionary using keyword arguments like d=False. The code above blows up the result of the expression following ** into a set of keyword arguments which are passed to the called function. This is certainly a reliable way to create dictionaries, and people seem to be at least accepting of this idiom, but I suspect that some may consider it Unpythonic. </disclaimer>


Yet another approach, which is likely the most intuitive if you will be using this pattern frequently, is to define your data as a list of flag values (True, False) mapped to flag names (single-character strings). You then transform this data definition into an inverted dictionary which maps flag names to flag values. This can be done quite succinctly with a nested list comprehension, but here’s a very readable implementation:

>>> 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}

The function invert_dict is a generator function. It generates, or yields — meaning that it repeatedly returns values of — key-value pairs. Those key-value pairs are the inverse of the contents of the two elements of the initial flags dictionary. They are fed into the dict constructor. In this case the dict constructor works differently from above because it’s being fed an iterator rather than a dictionary as its argument.


Drawing on @Chris Lutz’s comment: If you will really be using this for single-character values, you can actually do

>>> flags = {True: 'abc', False: 'de'}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

This works because Python strings are iterable, meaning that they can be moved through value by value. In the case of a string, the values are the individual characters in the string. So when they are being interpreted as iterables, as in this case where they are being used in a for loop, ['a', 'b', 'c'] and 'abc' are effectively equivalent. Another example would be when they are being passed to a function that takes an iterable, like tuple.

I personally wouldn’t do this because it doesn’t read intuitively: when I see a string, I expect it to be used as a single value rather than as a list. So I look at the first line and think “Okay, so there’s a True flag and a False flag.” So although it’s a possibility, I don’t think it’s the way to go. On the upside, it may help to explain the concepts of iterables and iterators more clearly.


Defining the function invert_dict such that it actually returns a dictionary is not a bad idea either; I mostly just didn’t do that because it doesn’t really help to explain how the routine works.


Apparently Python 2.7 has dictionary comprehensions, which would make for an extremely concise way to implement that function. This is left as an exercise to the reader, since I don’t have Python 2.7 installed :)

You can also combine some functions from the ever-versatile itertools module. As they say, There’s More Than One Way To Do It. Wait, the Python people don’t say that. Well, it’s true anyway in some cases. I would guess that Guido hath given unto us dictionary comprehensions so that there would be One Obvious Way to do this.


回答 1

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

回答 2

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

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

Use a list/dictionary or define your own class to encapsulate the stuff you’re defining, but if you need all those variables you can do:

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

回答 3

这是@Jeff M和我的评论的详细说明。

执行此操作时:

a, b = c, d

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

_ = c, d
a, b = _

第一行创建一个称为的元组_,其中包含两个元素,第一个元素的值为,c第二个元素的值为d。第二行将_元组解压缩到变量a和中b。这打破了您的一句话:

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 = _

它会为您提供与第一行完全相同的结果(如果将值或变量添加到一个部分而忘记更新另一个部分,则包括相同的exceptions)。但是,在这种特定情况下,yan的答案也许是最好的。

如果您有值列表,则仍然可以解压它们。您只需要先将其转换为元组即可。例如,以下代码将分别为a到分配一个介于0和9之间的值j

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

编辑:巧妙地把所有元素都分配为true,元素5(变量f)除外:

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

This is an elaboration on @Jeff M‘s and my comments.

When you do this:

a, b = c, d

It works with tuple packing and unpacking. You can separate the packing and unpacking steps:

_ = c, d
a, b = _

The first line creates a tuple called _ which has two elements, the first with the value of c and the second with the value of d. The second line unpacks the _ tuple into the variables a and b. This breaks down your one huge line:

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

Into two smaller lines:

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

It will give you the exact same result as the first line (including the same exception if you add values or variables to one part but forget to update the other). However, in this specific case, yan’s answer is perhaps the best.

If you have a list of values, you can still unpack them. You just have to convert it to a tuple first. For example, the following will assign a value between 0 and 9 to each of a through j, respectively:

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

EDIT: Neat trick to assign all of them as true except element 5 (variable f):

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

回答 4

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

取而代之的是,您可能希望将它们收集到一个更大的数据结构中,该结构可以存储在单个局部变量中。

直观的演示了如何使用字典来实现此目的,克里斯·卢茨(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)

当然,实际代码希望使用比“ DataHolder”和字母更大的有意义的名称。

When people are suggesting “use a list or tuple or other data structure”, what they’re saying is that, when you have a lot of different values that you care about, naming them all separately as local variables may not be the best way to do things.

Instead, you may want to gather them together into a larger data structure that can be stored in a single local variable.

intuited showed how you might use a dictionary for this, and Chris Lutz showed how to use a tuple for temporary storage before unpacking into separate variables, but another option to consider is to use collections.namedtuple to bundle the values more permanently.

So you might do something like:

# 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)

Real code would hopefully use more meaningful names than “DataHolder” and the letters of the alphabet, of course.


回答 5

实际上是什么问题?

如果您确实需要或想要10 abcdefghij,则一次或一次别无其他可能写a并写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 …指向False或True。如果在执行过程中这些值未更改,为什么要使用10个标识符?如果更改了,为什么要先定义标识符?如果没有事先定义,则会在需要时创建它们

你的问题对我来说很奇怪

What’s the problem , in fact ?

If you really need or want 10 a, b, c, d, e, f, g, h, i, j , there will be no other possibility, at a time or another, to write a and write b and write c…..

If the values are all different, you will be obliged to write for exemple

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]

that is to say defining the “variables” individually.

Or , using another writing, no need to use _ :

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]

or

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])

.

If some of them must have the same value, is the problem that it’s too long to write

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

?

Then you can write:

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

.

I don’t understand what is exactly your problem. If you want to write a code, you’re obliged to use the characters required by the writing of the instructions and definitions. What else ?

I wonder if your question isn’t the sign that you misunderstand something.

When one writes a = 10 , one don’t create a variable in the sense of “chunk of memory whose value can change”. This instruction:

  • either triggers the creation of an object of type integer and value 10 and the binding of a name ‘a’ with this object in the current namespace

  • or re-assign the name ‘a’ in the namespace to the object 10 (because ‘a’ was precedently binded to another object)

I say that because I don’t see the utility to define 10 identifiers a,b,c… pointing to False or True. If these values don’t change during the execution, why 10 identifiers ? And if they change, why defining the identifiers first ?, they will be created when needed if not priorly defined

Your question appears weird to me


回答 6

听起来您正以错误的方式对待我。

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

Sounds like you’re approaching your problem the wrong way to me.

Rewrite your code to use a tuple or write a class to store all of the data.


回答 7

我喜欢投票最多的答案;但是,它存在清单所示的问题。

  >> 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 breturn 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

I like the top voted answer; however, it has problems with list as shown.

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

This is discussed in great details (here), but the gist is that a and b are the same object with a is b returning True (same for id(a) == id(b)). Therefore if you change an index, you are changing the index of both a and b, since they are linked. To solve this you can do (source)

>> 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]

This can then be used as a variant of the top answer, which has the “desired” intuitive results

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

回答 8

在您的情况下,我将使用YAML。

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

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

但是,对于Google来说,它比较容易,因为它是一种标准,因此有成百上千的信息,您可以找到最适合您的理解的信息。;)

最好的祝福。

In your case, I would use YAML .

That is an elegant and professional standard for dealing with multiple parameters. The values are loaded from a separate file. You can see some info in this link:

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

But it is easier to Google it, as it is a standard, there are hundreds of info about it, you can find what best fits to your understanding. ;)

Best regards.


回答 9

JavaScript一样,您也可以在python的一行上使用多个语句a = 1; b = "Hello World"; c += 3

Like JavaScript you can also use multiple statements on one line in python a = 1; b = "Hello World"; c += 3