为什么Python允许我在一个作用域中定义变量,但在另一个作用域中使用它?

7

我看到可以在作用域内定义变量,然后在该作用域之外引用它。例如,以下代码可以运行:

if condition:
    x = 5
else:
    x = 10
print x

然而,这让我感到有些奇怪。如果你尝试在C语言中做这件事,变量X将无法正确地作用域:

if(condition) { int x = 5; }
else { int x = 10; }
print x; // Doesn't work: x is unavailable!

解决方法,在C语言中,是先声明X,然后再想要做什么:
int x;
if(condition) { x = 5; }
else { x = 10; }
print x; // Works!

因此,在Python中,我的本能是编写以下代码:
x = None
if condition:
    x = 5
else:
    x = 10
print x

然而,我意识到Python并不要求我这样做。有什么建议吗?在这种情况下是否有样式指南?


10
为什么你总是问问题却从不接受答案? - David Heffernan
顺便说一句:你应该放松对整个作用域问题的担忧。你的第一个代码块是完全没问题的。逻辑定律将至少在 Python 的下一个版本中保持不变 :) - detly
@DavidHeffernan 或许这个问题没有明确的答案?我很感激这次讨论。 - gatoatigrado
4个回答

17

在Python中,代码块不会创建新的作用域。而模块、类和函数会创建新的作用域。

另外:

x = 10
if condition:
    x = 5
print x

或:

x = 5
if not condition:
    x = 10
print x

2
这里有文档记录链接 - Björn Pollex
2
为了完整起见:生成器表达式、lambda表达式以及在Python 3中的列表推导式都会创建新的作用域。 - Sven Marnach
虽然不预定义变量是可能的,但这是明智的/良好的惯例吗?在业务逻辑块之前声明我们现在正在寻找特定变量x的值,这难道不至少更具描述性吗? - Tuukka Mustonen
将其设置为默认值,然后使用逻辑来更改值可以增加清晰度,但在将其设置为不相关的值(例如问题中的 None),然后无条件地更改它会稍微降低其清晰度。 - Ignacio Vazquez-Abrams

5

我的建议:

使用Python,而不是C。

在Python中,我们使用块。一个if就是一个块。在Python中,块并不一定意味着不同的作用域。


0
在你的例子中,你可以尝试这样做:
x = 10
if condiiton:
    x = 5
print x

至于为什么Python没有与C(以及C++和Java)相同的作用域规则,简短的答案是它们是不同的语言。长的答案与效率有关。在C中,这些作用域规则都在编译时处理,没有运行时开销。在Python中,它必须将内部作用域存储在一个新的dict中,这会增加开销。我相信还有其他原因,但这是一个重要的实际原因。


0

你没有创建新的作用域,因此没有作用域问题。

但是,请注意如果你做了这样的事情:

if foo:
    x = 10
print x

如果foo为False,您将会遇到一个NameError错误,因此您可能会遇到这样一种情况:您实际上确实希望在条件之外定义变量(或添加一个else来将其赋值为None)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接