标签归档:coding-style

在“ if”语句中设置多行条件的样式?[关闭]

问题:在“ if”语句中设置多行条件的样式?[关闭]

有时我将ifs中的长条条件分解为几行。最明显的方法是:

  if (cond1 == 'val1' and cond2 == 'val2' and
      cond3 == 'val3' and cond4 == 'val4'):
      do_something

在视觉上不是很吸引人,因为动作与条件融为一体。但是,这是使用正确的4个空格的Python缩进的自然方法。

目前,我正在使用:

  if (    cond1 == 'val1' and cond2 == 'val2' and
          cond3 == 'val3' and cond4 == 'val4'):
      do_something

但这不是很漂亮。:-)

您能推荐一种替代方法吗?

Sometimes I break long conditions in ifs onto several lines. The most obvious way to do this is:

  if (cond1 == 'val1' and cond2 == 'val2' and
      cond3 == 'val3' and cond4 == 'val4'):
      do_something

Isn’t very very appealing visually, because the action blends with the conditions. However, it is the natural way using correct Python indentation of 4 spaces.

For the moment I’m using:

  if (    cond1 == 'val1' and cond2 == 'val2' and
          cond3 == 'val3' and cond4 == 'val4'):
      do_something

But this isn’t very pretty. :-)

Can you recommend an alternative way?


回答 0

您不需要在第二条条件行上使用4个空格。可能使用:

if (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

另外,不要忘记空白比您想象的更灵活:

if (   
       cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something
if    (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

两者都相当丑陋。

也许丢了括号(尽管《风格指南》不鼓励这样做)?

if cond1 == 'val1' and cond2 == 'val2' and \
   cond3 == 'val3' and cond4 == 'val4':
    do_something

这至少使您与众不同。

甚至:

if cond1 == 'val1' and cond2 == 'val2' and \
                       cond3 == 'val3' and \
                       cond4 == 'val4':
    do_something

我想我更喜欢:

if cond1 == 'val1' and \
   cond2 == 'val2' and \
   cond3 == 'val3' and \
   cond4 == 'val4':
    do_something

这是《样式指南》,(自2010年起)建议使用括号。

You don’t need to use 4 spaces on your second conditional line. Maybe use:

if (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

Also, don’t forget the whitespace is more flexible than you might think:

if (   
       cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something
if    (cond1 == 'val1' and cond2 == 'val2' and 
       cond3 == 'val3' and cond4 == 'val4'):
    do_something

Both of those are fairly ugly though.

Maybe lose the brackets (the Style Guide discourages this though)?

if cond1 == 'val1' and cond2 == 'val2' and \
   cond3 == 'val3' and cond4 == 'val4':
    do_something

This at least gives you some differentiation.

Or even:

if cond1 == 'val1' and cond2 == 'val2' and \
                       cond3 == 'val3' and \
                       cond4 == 'val4':
    do_something

I think I prefer:

if cond1 == 'val1' and \
   cond2 == 'val2' and \
   cond3 == 'val3' and \
   cond4 == 'val4':
    do_something

Here’s the Style Guide, which (since 2010) recommends using brackets.


回答 1

在简并的情况下,我采用了以下内容:简而言之,其为AND或OR。

if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

它可以刮掉几个字符,并清楚表明该条件没有任何微妙之处。

I’ve resorted to the following in the degenerate case where it’s simply AND’s or OR’s.

if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

It shaves a few characters and makes it clear that there’s no subtlety to the condition.


回答 2

有人必须在这里提倡使用垂直空格!:)

if (     cond1 == val1
     and cond2 == val2
     and cond3 == val3
   ):
    do_stuff()

这使得每个条件都清晰可见。它还可以更清晰地表达更复杂的条件:

if (    cond1 == val1
     or 
        (     cond2_1 == val2_1
          and cond2_2 >= val2_2
          and cond2_3 != bad2_3
        )
   ):
    do_more_stuff()

是的,为了清楚起见,我们将权衡一些垂直房地产。IMO值得。

Someone has to champion use of vertical whitespace here! :)

if (     cond1 == val1
     and cond2 == val2
     and cond3 == val3
   ):
    do_stuff()

This makes each condition clearly visible. It also allows cleaner expression of more complex conditions:

if (    cond1 == val1
     or 
        (     cond2_1 == val2_1
          and cond2_2 >= val2_2
          and cond2_3 != bad2_3
        )
   ):
    do_more_stuff()

Yes, we’re trading off a bit of vertical real estate for clarity. Well worth it IMO.


回答 3

当我有一个非常大的if条件时,我更喜欢这种风格:

if (
    expr1
    and (expr2 or expr3)
    and hasattr(thingy1, '__eq__')
    or status=="HappyTimes"
):
    do_stuff()
else:
    do_other_stuff()

I prefer this style when I have a terribly large if-condition:

if (
    expr1
    and (expr2 or expr3)
    and hasattr(thingy1, '__eq__')
    or status=="HappyTimes"
):
    do_stuff()
else:
    do_other_stuff()

回答 4

这是我非常个人的看法:(在我看来)长时间条件是一种代码气味,建议将其重构为布尔返回函数/方法。例如:

def is_action__required(...):
    return (cond1 == 'val1' and cond2 == 'val2'
            and cond3 == 'val3' and cond4 == 'val4')

现在,如果我找到一种使多行条件看起来不错的方法,那么我可能会发现自己对满足这些条件感到满意,而无需进行重构。

另一方面,让它们扰乱我的审美意识可以促进重构。

因此,我的结论是,多个线路条件看起来很丑陋,这是避免它们的诱因。

Here’s my very personal take: long conditions are (in my view) a code smell that suggests refactoring into a boolean-returning function/method. For example:

def is_action__required(...):
    return (cond1 == 'val1' and cond2 == 'val2'
            and cond3 == 'val3' and cond4 == 'val4')

Now, if I found a way to make multi-line conditions look good, I would probably find myself content with having them and skip the refactoring.

On the other hand, having them perturb my aesthetic sense acts as an incentive for refactoring.

My conclusion, therefore, is that multiple line conditions should look ugly and this is an incentive to avoid them.


回答 5

这并没有太大改善,但是…

allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
                 cond3 == 'val3' and cond4 == 'val4')

if allCondsAreOK:
   do_something

This doesn’t improve so much but…

allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
                 cond3 == 'val3' and cond4 == 'val4')

if allCondsAreOK:
   do_something

回答 6

我建议将and关键字移至第二行,并将包含条件的所有行缩进,而不是四个空格:

if (cond1 == 'val1' and cond2 == 'val2'
  and cond3 == 'val3' and cond4 == 'val4'):
    do_something

这正是我在代码中解决此问题的方式。将关键字作为该行中的第一个单词使该条件更具可读性,并且减少空格的数量进一步将条件与动作区分开。

I suggest moving the and keyword to the second line and indenting all lines containing conditions with two spaces instead of four:

if (cond1 == 'val1' and cond2 == 'val2'
  and cond3 == 'val3' and cond4 == 'val4'):
    do_something

This is exactly how I solve this problem in my code. Having a keyword as the first word in the line makes the condition a lot more readable, and reducing the number of spaces further distinguishes condition from action.


回答 7

似乎值得引用PEP 0008(Python的官方样式指南),因为它以适度的长度评论了这个问题:

当- if语句的条件部分足够长以至于需要将其写成多行时,值得注意的是,两个字符关键字(即if),一个空格和一个左括号的组合会产生自然的4-多行条件的后续行的空格缩进。这可能与嵌套在if-statement中的缩进代码套件产生视觉冲突,该缩进代码套件自然也会缩进4个空格。对于如何(或是否)在视觉上进一步将这些条件行与if-statement 内的嵌套套件区分开,此PEP没有明确的位置。在这种情况下,可接受的选项包括但不限于:

# No extra indentation.
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()

# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

注意上面引用中的“不限于”;除了在样式指南中建议的方法外,在此问题的其他答案中建议的一些方法也是可以接受的。

It seems worth quoting PEP 0008 (Python’s official style guide), since it comments upon this issue at modest length:

When the conditional part of an if -statement is long enough to require that it be written across multiple lines, it’s worth noting that the combination of a two character keyword (i.e. if ), plus a single space, plus an opening parenthesis creates a natural 4-space indent for the subsequent lines of the multiline conditional. This can produce a visual conflict with the indented suite of code nested inside the if -statement, which would also naturally be indented to 4 spaces. This PEP takes no explicit position on how (or whether) to further visually distinguish such conditional lines from the nested suite inside the if -statement. Acceptable options in this situation include, but are not limited to:

# No extra indentation.
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()

# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

Note the “not limited to” in the quote above; besides the approaches suggested in the style guide, some of the ones suggested in other answers to this question are acceptable too.


回答 8

这就是我的工作,请记住“ all”和“ any”接受迭代,因此我将一个长条件放在列表中,然后让“ all”完成工作。

condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']

if all(condition):
   do_something

Here’s what I do, remember that “all” and “any” accepts an iterable, so I just put a long condition in a list and let “all” do the work.

condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']

if all(condition):
   do_something

回答 9

我很惊讶没有看到我的首选解决方案,

if (cond1 == 'val1' and cond2 == 'val2'
    and cond3 == 'val3' and cond4 == 'val4'):
    do_something

由于and是一个关键字,因此我的编辑器将其突出显示,并且看起来与其下方的do_something完全不同。

I’m surprised not to see my preferred solution,

if (cond1 == 'val1' and cond2 == 'val2'
    and cond3 == 'val3' and cond4 == 'val4'):
    do_something

Since and is a keyword, it gets highlighted by my editor, and looks sufficiently different from the do_something below it.


回答 10

加上@krawyoti所说的话…长时间的气味会散发出来,因为它们难以阅读且难以理解。使用函数或变量可使代码更清晰。在Python中,我更喜欢使用垂直空间,将括号括起来,并将逻辑运算符放在每行的开头,以使表达式看起来不像“浮动”。

conditions_met = (
    cond1 == 'val1' 
    and cond2 == 'val2' 
    and cond3 == 'val3' 
    and cond4 == 'val4'
    )
if conditions_met:
    do_something

如果需要多次评估条件(例如在while循环中),则最好使用局部函数。

Adding to what @krawyoti said… Long conditions smell because they are difficult to read and difficult to understand. Using a function or a variable makes the code clearer. In Python, I prefer to use vertical space, enclose parenthesis, and place the logical operators at the beginning of each line so the expressions don’t look like “floating”.

conditions_met = (
    cond1 == 'val1' 
    and cond2 == 'val2' 
    and cond3 == 'val3' 
    and cond4 == 'val4'
    )
if conditions_met:
    do_something

If the conditions need to be evaluated more than once, as in a while loop, then using a local function is best.


回答 11

就个人而言,我喜欢在长if语句中添加含义。我将不得不在代码中进行搜索以找到合适的示例,但这是我想到的第一个示例:假设我碰巧遇到了一些古怪的逻辑,我想根据许多变量来显示特定页面。

英语:“如果登录的用户不是管理员教师,而是普通教师,而不是学生本身…”

if not user.isAdmin() and user.isTeacher() and not user.isStudent():
    doSomething()

当然,这看起来不错,但是如果需要大量阅读,请阅读这些内容。我们如何将逻辑分配给有意义的标签。“标签”实际上是变量名:

displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
    showTeacherPanel()

这看起来似乎很愚蠢,但是您可能还有另一种情况,您仅在显示教师面板或默认情况下用户有权访问其他特定面板时才要显示其他项目:

if displayTeacherPanel or user.canSeeSpecialPanel():
    showSpecialPanel()

尝试在不使用变量来存储和标记逻辑的情况下编写上述条件,不仅会得到非常混乱,难以理解的逻辑语句,而且还会重复自己。尽管有合理的exceptions情况,但请记住:不要重复自己(DRY)。

Personally, I like to add meaning to long if-statements. I would have to search through code to find an appropriate example, but here’s the first example that comes to mind: let’s say I happen to run into some quirky logic where I want to display a certain page depending on many variables.

English: “If the logged-in user is NOT an administrator teacher, but is just a regular teacher, and is not a student themselves…”

if not user.isAdmin() and user.isTeacher() and not user.isStudent():
    doSomething()

Sure this might look fine, but reading those if statements is a lot of work. How about we assign the logic to label that makes sense. The “label” is actually the variable name:

displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
    showTeacherPanel()

This may seem silly, but you might have yet another condition where you ONLY want to display another item if, and only if, you’re displaying the teacher panel OR if the user has access to that other specific panel by default:

if displayTeacherPanel or user.canSeeSpecialPanel():
    showSpecialPanel()

Try writing the above condition without using variables to store and label your logic, and not only do you end up with a very messy, hard-to-read logical statement, but you also just repeated yourself. While there are reasonable exceptions, remember: Don’t Repeat Yourself (DRY).


回答 12

“ all”和“ any”对于相同类型案例的许多条件都很好。但是他们总是评估所有条件。如本例所示:

def c1():
    print " Executed c1"
    return False
def c2():
    print " Executed c2"
    return False


print "simple and (aborts early!)"
if c1() and c2():
    pass

print

print "all (executes all :( )"
if all((c1(),c2())):
    pass

print

“all” and “any” are nice for the many conditions of same type case. BUT they always evaluates all conditions. As shown in this example:

def c1():
    print " Executed c1"
    return False
def c2():
    print " Executed c2"
    return False


print "simple and (aborts early!)"
if c1() and c2():
    pass

print

print "all (executes all :( )"
if all((c1(),c2())):
    pass

print

回答 13

(我对标识符进行了小幅修改,因为固定宽度的名称不代表真实代码-至少不代表我遇到的真实代码-这将掩盖示例的可读性。)

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
    do_something

这对于“ and”和“ or”非常有效(重要的是它们排在第二行),但对于其他较长条件则远不如此。幸运的是,前者似乎是更常见的情况,而后者通常很容易用一个临时变量重写。(通常并不难,但是在重写时保留“和” /“或”的短路可能很困难或不太明显/可读性。)

由于我从您的博客文章中找到了有关C ++的问题,因此我将介绍我的C ++样式是相同的:

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
    do_something
}

(I’ve lightly modified the identifiers as fixed-width names aren’t representative of real code – at least not real code that I encounter – and will belie an example’s readability.)

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
    do_something

This works well for “and” and “or” (it’s important that they’re first on the second line), but much less so for other long conditions. Fortunately, the former seem to be the more common case while the latter are often easily rewritten with a temporary variable. (It’s usually not hard, but it can be difficult or much less obvious/readable to preserve the short-circuiting of “and”/”or” when rewriting.)

Since I found this question from your blog post about C++, I’ll include that my C++ style is identical:

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
    do_something
}

回答 14

简单明了,还通过了pep8检查:

if (
    cond1 and
    cond2
):
    print("Hello World!")

近年来,我一直偏爱alland any函数,因为我很少将And和Or混合使用,因此效果很好,并且具有生成器理解失败的额外优势:

if all([
    cond1,
    cond2,
]):
    print("Hello World!")

只记得传递一个可迭代的值!传递N参数是不正确的。

注意:any就像很多or比较,all就像很多and比较。


这与生成器理解很好地结合在一起,例如:

# Check if every string in a list contains a substring:
my_list = [
    'a substring is like a string', 
    'another substring'
]

if all('substring' in item for item in my_list):
   print("Hello World!")

# or

if all(
    'substring' in item
    for item in my_list
):
    print("Hello World!")

更多信息:生成器理解

Plain and simple, also passes pep8 checks:

if (
    cond1 and
    cond2
):
    print("Hello World!")

In recent times I have been preferring the all and any functions, since I rarely mix And and Or comparisons this works well, and has the additional advantage of Failing Early with generators comprehension:

if all([
    cond1,
    cond2,
]):
    print("Hello World!")

Just remember to pass in a single iterable! Passing in N-arguments is not correct.

Note: any is like many or comparisons, all is like many and comparisons.


This combines nicely with generator comprehensions, for example:

# Check if every string in a list contains a substring:
my_list = [
    'a substring is like a string', 
    'another substring'
]

if all('substring' in item for item in my_list):
   print("Hello World!")

# or

if all(
    'substring' in item
    for item in my_list
):
    print("Hello World!")

More on: generator comprehension


回答 15

如果我们仅在条件和身体之间插入一条额外的空白行,而其余部分以规范的方式进行,该怎么办?

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):

    do_something

ps我总是使用制表符,而不是空格。我无法微调…

What if we only insert an additional blank line between the condition and the body and do the rest in the canonical way?

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):

    do_something

p.s. I always use tabs, not spaces; I cannot fine-tune…


回答 16

我通常要做的是:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something

这样,右括号和冒号在视觉上标志着我们病情的结束。

What I usually do is:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something

this way the closing brace and colon visually mark the end of our condition.


回答 17

也为if语句提供多条件的所有受访者与所提出的问题一样丑陋。您不能通过做同样的事情来解决此问题。

甚至PEP 0008的答案也是令人反感的。

这是一种更具可读性的方法

condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
    pass

要我吃我的话吗?说服我,您需要多条件,并且我会逐字打印出来,并出于娱乐目的而食用。

All respondents that also provide multi-conditionals for the if statement is just as ugly as the problem presented. You don’t solve this problem by doing the same thing..

Even the PEP 0008 answer is repulsive.

Here is a far more readable approach

condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
    pass

Want me to eat my words? Convince me you need multi-conditionals and I’ll literally print this and eat it for your amusement.


回答 18

我认为@zkanda的解决方案稍作改动就可以了。如果您在各自的列表中有条件和值,则可以使用列表推导进行比较,这将使添加条件/值对的过程更加通用。

conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
    # do something

如果我确实想对这样的语句进行硬编码,出于可读性考虑,我会这样写:

if (condition1==value1) and (condition2==value2) and \
   (condition3==value3) and (condition4==value4):

并与iand操作员一起提出另一个解决方案:

proceed = True
for c, v in zip(conditions, values):
    proceed &= c==v

if proceed:
    # do something

I think @zkanda’s solution would be good with a minor twist. If you had your conditions and values in their own respective lists, you could use a list comprehension to do the comparison, which would make things a bit more general for adding condition/value pairs.

conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
    # do something

If I did want to hard-code a statement like this, I would write it like this for legibility:

if (condition1==value1) and (condition2==value2) and \
   (condition3==value3) and (condition4==value4):

And just to throw another solution out there with an iand operator:

proceed = True
for c, v in zip(conditions, values):
    proceed &= c==v

if proceed:
    # do something

回答 19

出于完整性考虑,仅提供了一些其他随机想法。如果它们对您有用,请使用它们。否则,您最好尝试其他方法。

您也可以使用字典来做到这一点:

>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True

这个选项比较复杂,但是您可能还会发现它有用:

class Klass(object):
    def __init__(self, some_vars):
        #initialize conditions here
    def __nonzero__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
                self.cond3 == 'val3' and self.cond4 == 'val4')

foo = Klass()
if foo:
    print "foo is true!"
else:
    print "foo is false!"

邓诺(Dunno)是否适合您,但这是您可以考虑的另一种选择。这是另一种方式:

class Klass(object):
    def __init__(self):
        #initialize conditions here
    def __eq__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
               self.cond3 == 'val3' and self.cond4 == 'val4')

x = Klass(some_values)
y = Klass(some_other_values)
if x == y:
    print 'x == y'
else:
    print 'x!=y'

我还没有测试过最后两个,但是如果您想使用这些概念,那么它们的概念应该足以让您开始工作。

(从记录来看,如果这只是一次性的事情,那么使用最初介绍的方法可能会更好。如果在很多地方进行比较,这些方法可能会增强可读性,从而使您不会因为它们有点hacky而感到难过。)

Just a few other random ideas for completeness’s sake. If they work for you, use them. Otherwise, you’re probably better off trying something else.

You could also do this with a dictionary:

>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True

This option is more complicated, but you may also find it useful:

class Klass(object):
    def __init__(self, some_vars):
        #initialize conditions here
    def __nonzero__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
                self.cond3 == 'val3' and self.cond4 == 'val4')

foo = Klass()
if foo:
    print "foo is true!"
else:
    print "foo is false!"

Dunno if that works for you, but it’s another option to consider. Here’s one more way:

class Klass(object):
    def __init__(self):
        #initialize conditions here
    def __eq__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
               self.cond3 == 'val3' and self.cond4 == 'val4')

x = Klass(some_values)
y = Klass(some_other_values)
if x == y:
    print 'x == y'
else:
    print 'x!=y'

The last two I haven’t tested, but the concepts should be enough to get you going if that’s what you want to go with.

(And for the record, if this is just a one time thing, you’re probably just better off using the method you presented at first. If you’re doing the comparison in lots of places, these methods may enhance readability enough to make you not feel so bad about the fact that they are kind of hacky.)


回答 20

我一直在努力寻找一种合适的方法来做到这一点,所以我只是想出了一个主意(不是灵丹妙药,因为这主要是一个品味问题)。

if bool(condition1 and
        condition2 and
        ...
        conditionN):
    foo()
    bar()

与我见过的其他解决方案相比,我发现此解决方案有一些优点,即,您恰好获得了额外的4个缩进空间(布尔),允许所有条件垂直排列,并且if语句的主体可以缩进一种清晰的方式 这也保留了对布尔运算符进行短路评估的好处,但是当然会增加基本上不执行任何操作的函数调用的开销。您可能会(有效地)争辩说,可以在此处使用任何返回其参数的函数而不是bool,但是就像我说的那样,这只是一个主意,最终是一个品味问题。

有趣的是,当我写这篇文章并思考“问题”时,我想到了另一个想法,它消除了函数调用的开销。为什么不通过使用额外的圆括号来表明我们将要输入复杂的条件?再说2个,相对于if语句的主体,给子条件一个2的空格缩进。例:

if (((foo and
      bar and
      frob and
      ninja_bear))):
    do_stuff()

我之所以喜欢这样,是因为当您看着它时,头上的铃铛立即响起,说:“嘿,这是一件复杂的事情!” 。是的,我知道括号并不能帮助提高可读性,但是这些条件应该很少出现,并且当它们出现时,您无论如何都要停下来仔细阅读它们(因为它们很复杂))。

无论如何,只有两个我在这里没有看到的建议。希望这可以帮助某人:)

I’ve been struggling to find a decent way to do this as well, so I just came up with an idea (not a silver bullet, since this is mainly a matter of taste).

if bool(condition1 and
        condition2 and
        ...
        conditionN):
    foo()
    bar()

I find a few merits in this solution compared to others I’ve seen, namely, you get exactly an extra 4 spaces of indentation (bool), allowing all conditions to line up vertically, and the body of the if statement can be indented in a clear(ish) way. This also keeps the benefits of short-circuit evaluation of boolean operators, but of course adds the overhead of a function call that basically does nothing. You could argue (validly) that any function returning its argument could be used here instead of bool, but like I said, it’s just an idea and it’s ultimately a matter of taste.

Funny enough, as I was writing this and thinking about the “problem”, I came up with yet another idea, which removes the overhead of a function call. Why not indicate that we’re about to enter a complex condition by using extra pairs of parentheses? Say, 2 more, to give a nice 2 space indent of the sub-conditions relative to the body of the if statement. Example:

if (((foo and
      bar and
      frob and
      ninja_bear))):
    do_stuff()

I kind of like this because when you look at it, a bell immediatelly rings in your head saying “hey, there’s a complex thing going on here!”. Yes, I know that parentheses don’t help readability, but these conditions should appear rarely enough, and when they do show up, you are going to have to stop and read them carefuly anyway (because they’re complex).

Anyway, just two more proposals that I haven’t seen here. Hope this helps someone :)


回答 21

您可以将其分为两行

total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
    do_something()

甚至一次添加一个条件。这样,至少可以将混乱与混乱分开if

You could split it into two lines

total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
    do_something()

Or even add on one condition at a time. That way, at least it separates the clutter from the if.


回答 22

我知道这个线程很旧,但是我有一些Python 2.7代码,PyCharm(4.5)仍然抱怨这种情况:

if foo is not None:
    if (cond1 == 'val1' and cond2 == 'val2' and
        cond3 == 'val3' and cond4 == 'val4'):
            # some comment about do_something
            do_something

即使PEP8警告“带有与下一个逻辑行相同的缩进的可视缩进行”,实际代码也完全可以吗?这不是“缩进过度”吗?

…有时候我希望Python会咬住子弹,并且用花括号将其消失。我不知道这些年来由于偶然的错误压痕而意外引入了多少个错误…

I know this thread is old, but I have some Python 2.7 code and PyCharm (4.5) still complains about this case:

if foo is not None:
    if (cond1 == 'val1' and cond2 == 'val2' and
        cond3 == 'val3' and cond4 == 'val4'):
            # some comment about do_something
            do_something

Even with the PEP8 warning “visually indented line with same indent as next logical line”, the actual code is completely OK? It’s not “over-indenting?”

…there are times I wish Python would’ve bit the bullet and just gone with curly braces. I wonder how many bugs have been accidentally introduced over the years due to accidental mis-indentation…


回答 23

将您的条件打包到一个列表中,然后再做。喜欢:

if False not in Conditions:
    do_something

Pack your conditions into a list, then do smth. like:

if False not in Conditions:
    do_something

回答 24

我发现当我的条件很长时,我通常会有一个简短的代码主体。在这种情况下,我只是将身体缩进两次,因此:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):
        do_something

I find that when I have long conditions, I often have a short code body. In that case, I just double-indent the body, thus:

if (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'):
        do_something

回答 25

  if cond1 == 'val1' and \
     cond2 == 'val2' and \
     cond3 == 'val3' and \
     cond4 == 'val4':
      do_something

或者,如果更清楚:

  if cond1 == 'val1'\
     and cond2 == 'val2'\
     and cond3 == 'val3'\
     and cond4 == 'val4':
      do_something

在这种情况下,缩进没有理由应为4的倍数,例如,请参见“与开孔定界符对齐”:

http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Indentation#Indentation

  if cond1 == 'val1' and \
     cond2 == 'val2' and \
     cond3 == 'val3' and \
     cond4 == 'val4':
      do_something

or if this is clearer:

  if cond1 == 'val1'\
     and cond2 == 'val2'\
     and cond3 == 'val3'\
     and cond4 == 'val4':
      do_something

There is no reason indent should be a multiple of 4 in this case, e.g. see “Aligned with opening delimiter”:

http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Indentation#Indentation


回答 26

这是另一种方法:

cond_list = ['cond1 == "val1"','cond2=="val2"','cond3=="val3"','cond4=="val4"']
if all([eval(i) for i in cond_list]):
 do something

这也使您可以轻松地添加另一个条件,而无需更改if语句,只需将另一个条件附加到列表即可:

cond_list.append('cond5=="val5"')

Here’s another approach:

cond_list = ['cond1 == "val1"','cond2=="val2"','cond3=="val3"','cond4=="val4"']
if all([eval(i) for i in cond_list]):
 do something

This also makes it easy to add another condition easily without changing the if statement by simply appending another condition to the list:

cond_list.append('cond5=="val5"')

回答 27

我通常使用:

if ((cond1 == 'val1' and cond2 == 'val2' and
     cond3 == 'val3' and cond4 == 'val4')):
    do_something()

I usually use:

if ((cond1 == 'val1' and cond2 == 'val2' and
     cond3 == 'val3' and cond4 == 'val4')):
    do_something()

回答 28

如果我们的if&else条件必须在其中执行多个语句,则我们可以像下面这样编写。每当我们有if else例子时,里面都有一个语句。

谢谢它为我工作。

#!/usr/bin/python
import sys
numberOfArgument =len(sys.argv)
weblogic_username =''
weblogic_password = ''
weblogic_admin_server_host =''
weblogic_admin_server_port =''


if numberOfArgument == 5:
        weblogic_username = sys.argv[1]
        weblogic_password = sys.argv[2]
        weblogic_admin_server_host =sys.argv[3]
        weblogic_admin_server_port=sys.argv[4]
elif numberOfArgument <5:
        print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ."
        weblogic_username = raw_input("Enter Weblogic user Name")
        weblogic_password = raw_input('Enter Weblogic user Password')
        weblogic_admin_server_host = raw_input('Enter Weblogic admin host ')
        weblogic_admin_server_port = raw_input('Enter Weblogic admin port')
#enfelif
#endIf

if our if & an else condition has to execute multiple statement inside of it than we can write like below. Every when we have if else example with one statement inside of it .

Thanks it work for me.

#!/usr/bin/python
import sys
numberOfArgument =len(sys.argv)
weblogic_username =''
weblogic_password = ''
weblogic_admin_server_host =''
weblogic_admin_server_port =''


if numberOfArgument == 5:
        weblogic_username = sys.argv[1]
        weblogic_password = sys.argv[2]
        weblogic_admin_server_host =sys.argv[3]
        weblogic_admin_server_port=sys.argv[4]
elif numberOfArgument <5:
        print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ."
        weblogic_username = raw_input("Enter Weblogic user Name")
        weblogic_password = raw_input('Enter Weblogic user Password')
        weblogic_admin_server_host = raw_input('Enter Weblogic admin host ')
        weblogic_admin_server_port = raw_input('Enter Weblogic admin port')
#enfelif
#endIf

回答 29

请原谅我,但是碰巧我对#Python的了解不如在座的任何人,但是碰巧我在3D BIM建模中编写自己的对象时发现了类似的东西,因此我将使算法适应python的

我在这里发现的问题是双面的:

  1. 对于可能会尝试解密脚本的人,我认为我似乎很陌生。
  2. 如果更改了这些值(最可能的话),或者必须添加新的条件(损坏的架构),则代码维护的成本将很高。

要绕过所有这些问题,您的脚本必须像这样

param_Val01 = Value 01   #give a meaningful name for param_Val(i) preferable an integer
param_Val02 = Value 02
param_Val03 = Value 03
param_Val04 = Value 04   # and ... etc

conditions = 0           # this is a value placeholder

########
Add script that if true will make:

conditions = conditions + param_Val01   #value of placeholder is updated
########

### repeat as needed


if conditions = param_Val01 + param_Val02 + param_Val03 + param_Val04:
    do something

这种方法的优点:

  1. 脚本可读。

  2. 脚本可以轻松维护。

  3. 条件是对表示所需条件的值之和进行的1比较操作。
  4. 无需多级条件

希望对大家有帮助

Pardon my noobness, but it happens that I’m not as knowledgeable of #Python as anyone of you here, but it happens that I have found something similar when scripting my own objects in a 3D BIM modeling, so I will adapt my algorithm to that of python.

The problem that I find here, is double sided:

  1. Values my seem foreign for someone who may try to decipher the script.
  2. Code maintenance will come at a high cost, if those values are changed (most probable), or if new conditions must be added (broken schema)

Do to bypass all these problems, your script must go like this

param_Val01 = Value 01   #give a meaningful name for param_Val(i) preferable an integer
param_Val02 = Value 02
param_Val03 = Value 03
param_Val04 = Value 04   # and ... etc

conditions = 0           # this is a value placeholder

########
Add script that if true will make:

conditions = conditions + param_Val01   #value of placeholder is updated
########

### repeat as needed


if conditions = param_Val01 + param_Val02 + param_Val03 + param_Val04:
    do something

Pros of this method:

  1. Script is readable.

  2. Script can be easy maintained.

  3. conditions is a 1 comparison operation to a sum of values that represents the desired conditions.
  4. No need for multilevel conditions

Hope it help you all


如何从函数返回多个值?[关闭]

问题:如何从函数返回多个值?[关闭]

用支持它的语言返回多个值的规范方法通常是麻烦的

选项:使用元组

考虑下面这个简单的例子:

def f(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return (y0, y1, y2)

但是,随着返回值的数量增加,这很快就会成为问题。如果要返回四个或五个值怎么办?当然,您可以继续修改它们,但是很容易忘记哪个值在哪里。在任何要接收它们的地方打开它们的包装也是很丑陋的。

选项:使用字典

下一步的逻辑步骤似乎是引入某种“记录符号”。在Python中,显而易见的方法是使用dict

考虑以下:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0': y0, 'y1': y1 ,'y2': y2}

(请注意,y0,y1和y2只是抽象标识符。正如所指出的,实际上,您将使用有意义的标识符。)

现在,我们有了一种机制,可以投影出返回对象的特定成员。例如,

result['y0']

选项:使用类

但是,还有另一种选择。相反,我们可以返回一个特殊的结构。我已经在Python的上下文中对此进行了框架化,但是我确信它也适用于其他语言。确实,如果您使用C语言工作,这很可能是您唯一的选择。开始:

class ReturnValue:
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return ReturnValue(y0, y1, y2)

在Python中,前面的两个在管道方面可能非常相似-毕竟{ y0, y1, y2 }最终只是__dict__ReturnValue

Python提供了一项附加功能,尽管对于微小的对象,__slots__属性。该类可以表示为:

class ReturnValue(object):
  __slots__ = ["y0", "y1", "y2"]
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

Python参考手册中

__slots__声明采用一系列实例变量,并在每个实例中仅保留足够的空间来容纳每个变量的值。因为__dict__未为每个实例创建空间,所以节省了空间。

选项:使用数据类(Python 3.7+)

使用Python 3.7的新数据类,返回一个具有自动添加的特殊方法,键入和其他有用工具的类:

@dataclass
class Returnvalue:
    y0: int
    y1: float
    y3: int

def total_cost(x):
    y0 = x + 1
    y1 = x * 3
    y2 = y0 ** y3
    return ReturnValue(y0, y1, y2)

选项:使用列表

我忽略的另一个建议来自蜥蜴人比尔:

def h(x):
  result = [x + 1]
  result.append(x * 3)
  result.append(y0 ** y3)
  return result

这是我最不喜欢的方法。我想我对接触Haskell感到很受污染,但是混合类型列表的想法一直让我感到不舒服。在此特定示例中,列表为“非混合”类型,但可以想象是这样。

据我所知,以这种方式使用的列表实际上对元组没有任何好处。Python中列表和元组之间的唯一真正区别是列表是可变的,而元组则不是。

我个人倾向于继承函数式编程的约定:对任何数量的相同类型的元素使用列表,对固定数量的预定类型的元素使用元组。

在冗长的序言之后,出现了不可避免的问题。(您认为)哪种方法最好?

The canonical way to return multiple values in languages that support it is often tupling.

Option: Using a tuple

Consider this trivial example:

def f(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return (y0, y1, y2)

However, this quickly gets problematic as the number of values returned increases. What if you want to return four or five values? Sure, you could keep tupling them, but it gets easy to forget which value is where. It’s also rather ugly to unpack them wherever you want to receive them.

Option: Using a dictionary

The next logical step seems to be to introduce some sort of ‘record notation’. In Python, the obvious way to do this is by means of a dict.

Consider the following:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0': y0, 'y1': y1 ,'y2': y2}

(Just to be clear, y0, y1, and y2 are just meant as abstract identifiers. As pointed out, in practice you’d use meaningful identifiers.)

Now, we have a mechanism whereby we can project out a particular member of the returned object. For example,

result['y0']

Option: Using a class

However, there is another option. We could instead return a specialized structure. I’ve framed this in the context of Python, but I’m sure it applies to other languages as well. Indeed, if you were working in C this might very well be your only option. Here goes:

class ReturnValue:
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return ReturnValue(y0, y1, y2)

In Python the previous two are perhaps very similar in terms of plumbing – after all { y0, y1, y2 } just end up being entries in the internal __dict__ of the ReturnValue.

There is one additional feature provided by Python though for tiny objects, the __slots__ attribute. The class could be expressed as:

class ReturnValue(object):
  __slots__ = ["y0", "y1", "y2"]
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

From the Python Reference Manual:

The __slots__ declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because __dict__ is not created for each instance.

Option: Using a dataclass (Python 3.7+)

Using Python 3.7’s new dataclasses, return a class with automatically added special methods, typing and other useful tools:

@dataclass
class Returnvalue:
    y0: int
    y1: float
    y3: int

def total_cost(x):
    y0 = x + 1
    y1 = x * 3
    y2 = y0 ** y3
    return ReturnValue(y0, y1, y2)

Option: Using a list

Another suggestion which I’d overlooked comes from Bill the Lizard:

def h(x):
  result = [x + 1]
  result.append(x * 3)
  result.append(y0 ** y3)
  return result

This is my least favorite method though. I suppose I’m tainted by exposure to Haskell, but the idea of mixed-type lists has always felt uncomfortable to me. In this particular example the list is -not- mixed type, but it conceivably could be.

A list used in this way really doesn’t gain anything with respect to the tuple as far as I can tell. The only real difference between lists and tuples in Python is that lists are mutable, whereas tuples are not.

I personally tend to carry over the conventions from functional programming: use lists for any number of elements of the same type, and tuples for a fixed number of elements of predetermined types.

Question

After the lengthy preamble, comes the inevitable question. Which method (do you think) is best?


回答 0

为此,在2.6中添加了命名元组。另请参见os.stat以获取类似的内置示例。

>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(1, y=2)
>>> p.x, p.y
1 2
>>> p[0], p[1]
1 2

在最新版本的Python 3(我认为是3.6+)中,新typing库提供了NamedTuple使命名元组更易于创建和更强大的类。通过继承,typing.NamedTuple您可以使用文档字符串,默认值和类型注释。

示例(来自文档):

class Employee(NamedTuple):  # inherit from typing.NamedTuple
    name: str
    id: int = 3  # default value

employee = Employee('Guido')
assert employee.id == 3

Named tuples were added in 2.6 for this purpose. Also see os.stat for a similar builtin example.

>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(1, y=2)
>>> p.x, p.y
1 2
>>> p[0], p[1]
1 2

In recent versions of Python 3 (3.6+, I think), the new typing library got the NamedTuple class to make named tuples easier to create and more powerful. Inheriting from typing.NamedTuple lets you use docstrings, default values, and type annotations.

Example (From the docs):

class Employee(NamedTuple):  # inherit from typing.NamedTuple
    name: str
    id: int = 3  # default value

employee = Employee('Guido')
assert employee.id == 3

回答 1

对于小型项目,我发现使用元组最简单。当这变得难以管理时(而不是之前),我开始将事物分组为逻辑结构,但是我认为您建议使用字典和ReturnValue对象是错误的(或者过于简单)。

返回与键的字典"y0""y1""y2"等不提供任何优势元组。返回一个ReturnValue实例与性能.y0.y1.y2等不提供任何元组过任何优势。如果您想到达任何地方,就需要开始命名事物,并且无论如何都可以使用元组来命名:

def get_image_data(filename):
    [snip]
    return size, (format, version, compression), (width,height)

size, type, dimensions = get_image_data(x)

恕我直言,除元组之外,唯一好的技术是使用适当的方法和属性返回真实对象,就像您从re.match()或获取的那样open(file)

For small projects I find it easiest to work with tuples. When that gets too hard to manage (and not before) I start grouping things into logical structures, however I think your suggested use of dictionaries and ReturnValue objects is wrong (or too simplistic).

Returning a dictionary with keys "y0", "y1", "y2", etc. doesn’t offer any advantage over tuples. Returning a ReturnValue instance with properties .y0, .y1, .y2, etc. doesn’t offer any advantage over tuples either. You need to start naming things if you want to get anywhere, and you can do that using tuples anyway:

def get_image_data(filename):
    [snip]
    return size, (format, version, compression), (width,height)

size, type, dimensions = get_image_data(x)

IMHO, the only good technique beyond tuples is to return real objects with proper methods and properties, like you get from re.match() or open(file).


回答 2

许多答案表明您需要返回某种类型的集合,例如字典或列表。您可以省去多余的语法,而只需写出返回值(以逗号分隔)即可。注意:从技术上讲,这将返回一个元组。

def f():
    return True, False
x, y = f()
print(x)
print(y)

给出:

True
False

A lot of the answers suggest you need to return a collection of some sort, like a dictionary or a list. You could leave off the extra syntax and just write out the return values, comma-separated. Note: this technically returns a tuple.

def f():
    return True, False
x, y = f()
print(x)
print(y)

gives:

True
False

回答 3

我投票给字典。

我发现,如果我创建的函数返回的变量超过2-3个,则将它们折叠成字典。否则,我往往会忘记所返回内容的顺序和内容。

另外,引入“特殊”结构会使您的代码更难以遵循。(其他人将不得不搜索代码以找出它是什么)

如果您担心类型查找,请使用描述性字典键,例如“ x值列表”。

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

I vote for the dictionary.

I find that if I make a function that returns anything more than 2-3 variables I’ll fold them up in a dictionary. Otherwise I tend to forget the order and content of what I’m returning.

Also, introducing a ‘special’ structure makes your code more difficult to follow. (Someone else will have to search through the code to find out what it is)

If your concerned about type look up, use descriptive dictionary keys, for example, ‘x-values list’.

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

回答 4

另一种选择是使用生成器:

>>> def f(x):
        y0 = x + 1
        yield y0
        yield x * 3
        yield y0 ** 4


>>> a, b, c = f(5)
>>> a
6
>>> b
15
>>> c
1296

尽管IMHO元组通常是最好的,除非返回的值是封装在类中的候选对象。

Another option would be using generators:

>>> def f(x):
        y0 = x + 1
        yield y0
        yield x * 3
        yield y0 ** 4


>>> a, b, c = f(5)
>>> a
6
>>> b
15
>>> c
1296

Although IMHO tuples are usually best, except in cases where the values being returned are candidates for encapsulation in a class.


回答 5

我更喜欢在元组感到“自然”时使用元组。坐标是一个典型示例,其中单独的对象可以独立站立,例如在单轴缩放计算中,顺序很重要。注意:如果我可以对项目进行排序或改组而不会对组的含义造成不利影响,那么我可能不应该使用元组。

仅当分组的对象并不总是相同时,我才使用字典作为返回值。考虑可选的电子邮件标题。

对于其余的情况,如果分组的对象在组内具有固有的含义,或者需要具有自己方法的成熟对象,则使用类。

I prefer to use tuples whenever a tuple feels “natural”; coordinates are a typical example, where the separate objects can stand on their own, e.g. in one-axis only scaling calculations, and the order is important. Note: if I can sort or shuffle the items without an adverse effect to the meaning of the group, then I probably shouldn’t use a tuple.

I use dictionaries as a return value only when the grouped objects aren’t always the same. Think optional email headers.

For the rest of the cases, where the grouped objects have inherent meaning inside the group or a fully-fledged object with its own methods is needed, I use a class.


回答 6

我更喜欢:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

似乎其他所有东西只是做相同事情的额外代码。

I prefer:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

It seems everything else is just extra code to do the same thing.


回答 7

>>> def func():
...    return [1,2,3]
...
>>> a,b,c = func()
>>> a
1
>>> b
2
>>> c
3
>>> def func():
...    return [1,2,3]
...
>>> a,b,c = func()
>>> a
1
>>> b
2
>>> c
3

回答 8

通常,“专用结构”实际上是具有其自身方法的对象的当前状态。

class Some3SpaceThing(object):
  def __init__(self,x):
    self.g(x)
  def g(self,x):
    self.y0 = x + 1
    self.y1 = x * 3
    self.y2 = y0 ** y3

r = Some3SpaceThing( x )
r.y0
r.y1
r.y2

我希望在可能的地方找到匿名结构的名称。有意义的名称使事情变得更清楚。

Generally, the “specialized structure” actually IS a sensible current state of an object, with its own methods.

class Some3SpaceThing(object):
  def __init__(self,x):
    self.g(x)
  def g(self,x):
    self.y0 = x + 1
    self.y1 = x * 3
    self.y2 = y0 ** y3

r = Some3SpaceThing( x )
r.y0
r.y1
r.y2

I like to find names for anonymous structures where possible. Meaningful names make things more clear.


回答 9

Python的元组,字典和对象为程序员提供了在小型数据结构(“事物”)的形式和便利之间的平滑权衡。对我而言,如何表示事物的选择主要取决于我将如何使用结构。在C ++中,即使您可以合法地将方法放在; 上,也struct仅用于纯数据项和class带有方法的对象是一种常见的约定struct。我的习惯与Python类似,用dicttuple代替struct

对于坐标集,我将使用a tuple而不是点class或a dict(并且请注意,您可以将a tuple用作字典键,因此dicts是非常好的稀疏多维数组)。

如果我要遍历所有东西,我更喜欢tuple在迭代中解包s:

for score,id,name in scoreAllTheThings():
    if score > goodScoreThreshold:
        print "%6.3f #%6d %s"%(score,id,name)

…由于对象版本更易阅读:

for entry in scoreAllTheThings():
    if entry.score > goodScoreThreshold:
        print "%6.3f #%6d %s"%(entry.score,entry.id,entry.name)

…更不用说了dict

for entry in scoreAllTheThings():
    if entry['score'] > goodScoreThreshold:
        print "%6.3f #%6d %s"%(entry['score'],entry['id'],entry['name'])

如果该事物被广泛使用,并且您发现自己在代码中的多个位置对它执行了类似的非平凡操作,那么通常值得用适当的方法将其变成一个类对象。

最后,如果我要与非Python系统组件交换数据,那么我通常会将它们放在a中,dict因为这最适合JSON序列化。

Python’s tuples, dicts, and objects offer the programmer a smooth tradeoff between formality and convenience for small data structures (“things”). For me, the choice of how to represent a thing is dictated mainly by how I’m going to use the structure. In C++, it’s a common convention to use struct for data-only items and class for objects with methods, even though you can legally put methods on a struct; my habit is similar in Python, with dict and tuple in place of struct.

For coordinate sets, I’ll use a tuple rather than a point class or a dict (and note that you can use a tuple as a dictionary key, so dicts make great sparse multidimensional arrays).

If I’m going to be iterating over a list of things, I prefer unpacking tuples on the iteration:

for score,id,name in scoreAllTheThings():
    if score > goodScoreThreshold:
        print "%6.3f #%6d %s"%(score,id,name)

…as the object version is more cluttered to read:

for entry in scoreAllTheThings():
    if entry.score > goodScoreThreshold:
        print "%6.3f #%6d %s"%(entry.score,entry.id,entry.name)

…let alone the dict.

for entry in scoreAllTheThings():
    if entry['score'] > goodScoreThreshold:
        print "%6.3f #%6d %s"%(entry['score'],entry['id'],entry['name'])

If the thing is widely used, and you find yourself doing similar non-trivial operations on it in multiple places in the code, then it’s usually worthwhile to make it a class object with appropriate methods.

Finally, if I’m going to be exchanging data with non-Python system components, I’ll most often keep them in a dict because that’s best suited to JSON serialization.


回答 10

S.Lott关于命名容器类的建议的+1。

对于Python 2.6及更高版本,命名元组提供了一种轻松创建这些容器类的有用方法,其结果是“重量轻,并且不需要比常规元组更多的内存”。

+1 on S.Lott’s suggestion of a named container class.

For Python 2.6 and up, a named tuple provides a useful way of easily creating these container classes, and the results are “lightweight and require no more memory than regular tuples”.


回答 11

在像Python这样的语言中,我通常会使用字典,因为与创建新类相比,它所涉及的开销更少。

但是,如果我发现自己不断返回相同的变量集,则可能涉及一个我要考虑的新类。

In languages like Python, I would usually use a dictionary as it involves less overhead than creating a new class.

However, if I find myself constantly returning the same set of variables, then that probably involves a new class that I’ll factor out.


回答 12

我将使用字典来传递和从函数返回值:

使用form中定义的变量form

form = {
    'level': 0,
    'points': 0,
    'game': {
        'name': ''
    }
}


def test(form):
    form['game']['name'] = 'My game!'
    form['level'] = 2

    return form

>>> print(test(form))
{u'game': {u'name': u'My game!'}, u'points': 0, u'level': 2}

对于我和处理单元而言,这是最有效的方法。

您只需要传递一个指针并返回一个指针即可。

在代码中进行更改时,不必更改函数的参数(成千上万个)。

I would use a dict to pass and return values from a function:

Use variable form as defined in form.

form = {
    'level': 0,
    'points': 0,
    'game': {
        'name': ''
    }
}


def test(form):
    form['game']['name'] = 'My game!'
    form['level'] = 2

    return form

>>> print(test(form))
{u'game': {u'name': u'My game!'}, u'points': 0, u'level': 2}

This is the most efficient way for me and for processing unit.

You have to pass just one pointer in and return just one pointer out.

You do not have to change functions’ (thousands of them) arguments whenever you make a change in your code.


回答 13

“最佳”是部分主观的决定。在可接受不可变的一般情况下,将元组用于小的收益集。当不需要可变性时,元组总是比列表更可取。

对于更复杂的返回值,或者对于形式化很有价值(即高价值代码)的情况,命名元组更好。对于最复杂的情​​况,对象通常是最好的。但是,实际情况才是最重要的。如果返回一个对象是有意义的,因为那是您在函数末尾自然所拥有的(例如Factory模式),则返回该对象。

正如智者所说:

过早的优化是编程中所有邪恶(或至少是大多数邪恶)的根源。

“Best” is a partially subjective decision. Use tuples for small return sets in the general case where an immutable is acceptable. A tuple is always preferable to a list when mutability is not a requirement.

For more complex return values, or for the case where formality is valuable (i.e. high value code) a named tuple is better. For the most complex case an object is usually best. However, it’s really the situation that matters. If it makes sense to return an object because that is what you naturally have at the end of the function (e.g. Factory pattern) then return the object.

As the wise man said:

Premature optimization is the root of all evil (or at least most of it) in programming.