2014-11-07 59 views
2

我整个结构像这样的一段代码(简化的问题)来了:Python中的缩进不总是必要的吗?

while True: 
    if x == y: break 

我的Python的理解迄今为止的是,解释是高度依赖于制表符/空格理解事物的内容一样循环和条件,但上面的代码风格没有问题,这表明这不是真的。

有人可以解释细微差别吗?

回答

4

全部细节在参考文档Compound Statements中进行了说明。但作为一个简要总结:

任何“复合语句”,像if可以采取月结的要么缩进套房,或内嵌简单的语句列表。*

那么,这些有什么区别?

if x == y: 
    break 

if x == y: break 

真的没什么,除了第一个通常被认为更具可读性和惯用性。 (PEP 8,官方风格指南,说第二种形式是“普遍不鼓励”,但“有时候可以在同一条线上放一个if/for/while与小型身体”。)**

这些有完全相同的语义,性能等。他们甚至会编译成完全相同的字节码。有一个小的语法差异,但它只影响你将它们嵌入到各种非法结构中的错误消息。


那么,你可以在那里放些比break更复杂的东西吗?

是的。请注意,这是一个简单的声明列表。这意味着你可以有多个用分号隔开的简单语句:

if x == y: print('Hey!'); x = -x; break 

但是,这是令人难以置信的糟糕风格。除非你想赢得代码高尔夫比赛,否则不要这样做。

但也有限制。请注意,这是一个简单的语句列表。这意味着没有复合语句。这是非法的:

if x == y: while True: print('loopy') 

您可以看到简单陈述here的完整列表。


*内联语句列表仍然被认为是在正式语法一套房。但是在宽松的讨论中,套件更多时候意味着只是缩进块替代方案,而不是内联替代方案。

**以我的经验,由经验丰富的开发者看到这个代码中最常见的地方实际上是地方PEP 8说要永远做一个:用一堆空函数的类可以让他们在一行,如def spam(self): pass。这可能会使他们难以粘贴到交互式解释器中,这可能是PEP 8说永远不会这样做的原因。

+0

奇妙的差异细分。谢谢你。读者的Python知识/技能缺乏假设使得这个答案成为赢家。 – 2014-11-07 01:23:23

-1

这就是一个statemment和一个复合语句之间的区别。例如,在C你可能会做这样的事情

for(i=0; i<10; i++) printf("something"); 

for(i=0; i<10; i++) {printf("something");} 

for循环只是执行一个语句。但是,当您包括大括号内多于一个的语句,例如像

for(i=0; i<10; i++) {printf("something"); printf("something else");} 

然后在大括号内的整个事情被当作一个语句。

它与Python一样...

if x == y: 
    print 'abcd' # These two statements are treated as 1 block 
    break   # of statements 

如果你只是有一个说法,你不会需要定义一个块。

+0

这真是一个虚假的平行线。特别是因为你可以写'if x == y:print'abcd';休息“,它工作得很好。 – abarnert 2014-11-07 01:09:46

+0

实际上,使用分号分隔行仍然被认为是Python中的复合语句:https://docs.python.org/2/reference/compound_stmts.html – ssm 2014-11-07 03:15:13

+0

不,它不是。这是一个'stmt_list',它不是一种'compound_stmt'。事实上,如果你看一下它,那个页面上的'statement'被定义为'stmt_list'或'compound_stmt',所以它们显然是不同的东西。 – abarnert 2014-11-07 20:00:13

1

在Python中,如果块只包含单个语句,您可以随时用一行代替预期的块。

E.g.

def f(x): return x 

def f(x): 
    return x 

是等同的。这同样适用于在Python任何其他块预计语法:

  • 如果,否则,ELIF,对,同时,DEF,类...这里
+1

这不是正确的规则。如果单个语句不能内联(比如另一个单行块语句),并且可以很容易地在行上放置多个语句,比如'if foo:print(x),print(y)'',那么有很多。 – abarnert 2014-11-07 01:01:24

+0

使用'''工作的原因是因为print(x),print(y)'计算为'tuple'。所以在你刚才描述的情况下,print(x),print(y)'要求python评估一个将返回一个“元组”的语句。这通常用于'x,y = 5,6等语句中。事实上,你可以在代码中单独放置任何常量,并且程序流将不受影响。那是因为每一行都被评估过,如果'='操作符不存在,结果就被丢弃了。这就是为什么有些人经常使用多行字符串而不是'#'作为他们的评论。 – ssm 2014-11-07 03:30:53

+0

@ssm:对不起,这是'if foo:print(x); print(y)',这是一个包含两个简单语句的语句列表。 – abarnert 2014-11-07 20:00:58

2

缩进不是必需的,因为你的有simple_stmtbreak,在ifsuite:不需要

... 
if_stmt  ::= "if" expression ":" suite 
       ("elif" expression ":" suite)* 
       ["else" ":" suite] 
... 
suite   ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT 
statement  ::= stmt_list NEWLINE | compound_stmt 
... 
stmt_list  ::= simple_stmt (";" simple_stmt)* [";"] 
... 

在这种情况下缩进。

你只能用simple statements做到这一点,像returnbreak,但你不能有一个compound statementsifwhile,无压痕。

+0

我在想,说实际的语法是一个坏主意,但现在我看到它发布在这里,我认为即使很多新手也会得到它。确定+1。 – abarnert 2014-11-07 01:18:30