我整个结构像这样的一段代码(简化的问题)来了:Python中的缩进不总是必要的吗?
while True:
if x == y: break
我的Python的理解迄今为止的是,解释是高度依赖于制表符/空格理解事物的内容一样循环和条件,但上面的代码风格没有问题,这表明这不是真的。
有人可以解释细微差别吗?
我整个结构像这样的一段代码(简化的问题)来了:Python中的缩进不总是必要的吗?
while True:
if x == y: break
我的Python的理解迄今为止的是,解释是高度依赖于制表符/空格理解事物的内容一样循环和条件,但上面的代码风格没有问题,这表明这不是真的。
有人可以解释细微差别吗?
全部细节在参考文档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说永远不会这样做的原因。
这就是一个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
如果你只是有一个说法,你不会需要定义一个块。
这真是一个虚假的平行线。特别是因为你可以写'if x == y:print'abcd';休息“,它工作得很好。 – abarnert 2014-11-07 01:09:46
实际上,使用分号分隔行仍然被认为是Python中的复合语句:https://docs.python.org/2/reference/compound_stmts.html – ssm 2014-11-07 03:15:13
不,它不是。这是一个'stmt_list',它不是一种'compound_stmt'。事实上,如果你看一下它,那个页面上的'statement'被定义为'stmt_list'或'compound_stmt',所以它们显然是不同的东西。 – abarnert 2014-11-07 20:00:13
在Python中,如果块只包含单个语句,您可以随时用一行代替预期的块。
E.g.
def f(x): return x
def f(x):
return x
是等同的。这同样适用于在Python任何其他块预计语法:
这不是正确的规则。如果单个语句不能内联(比如另一个单行块语句),并且可以很容易地在行上放置多个语句,比如'if foo:print(x),print(y)'',那么有很多。 – abarnert 2014-11-07 01:01:24
使用'''工作的原因是因为print(x),print(y)'计算为'tuple'。所以在你刚才描述的情况下,print(x),print(y)'要求python评估一个将返回一个“元组”的语句。这通常用于'x,y = 5,6等语句中。事实上,你可以在代码中单独放置任何常量,并且程序流将不受影响。那是因为每一行都被评估过,如果'='操作符不存在,结果就被丢弃了。这就是为什么有些人经常使用多行字符串而不是'#'作为他们的评论。 – ssm 2014-11-07 03:30:53
@ssm:对不起,这是'if foo:print(x); print(y)',这是一个包含两个简单语句的语句列表。 – abarnert 2014-11-07 20:00:58
缩进不是必需的,因为你的有simple_stmt
,break
,在if
的suite
:不需要
...
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做到这一点,像return
或break
,但你不能有一个compound statements,if
像while
,无压痕。
我在想,说实际的语法是一个坏主意,但现在我看到它发布在这里,我认为即使很多新手也会得到它。确定+1。 – abarnert 2014-11-07 01:18:30
奇妙的差异细分。谢谢你。读者的Python知识/技能缺乏假设使得这个答案成为赢家。 – 2014-11-07 01:23:23