Cha*_*lie 5 python variables scope
我有这样的代码
if condition:
a = f(x)
else:
a = g(y)
Run Code Online (Sandbox Code Playgroud)
a
块内部的初始化对我来说很糟糕.可以写得更好吗?
我不能使用三元运算符,因为函数和/或参数列表的名称很长.说"长"我的意思是以下表达式
a = f(x) if condition else g(y)
Run Code Online (Sandbox Code Playgroud)
需要超过79(有时甚至大于119)的符号使用实名的代替a
,f
,g
,x
,y
和condition
.使用多个斜杠会使代码变得丑陋和混乱.
我不想a
用默认函数初始化其中一个函数的结果,因为这两个函数都很慢,我不能允许这样的开销
a = g(y)
if condition:
a = f(x)
Run Code Online (Sandbox Code Playgroud)
我可以初始化变量None
,但这个解决方案是否已足够?
a = None
if condition:
a = f(x)
else:
a = g(y)
Run Code Online (Sandbox Code Playgroud)
让我解释一下我的立场:在C和C++中,块内部的变量都以块作为其范围.在ES6 let
中引入了关键字 - 它允许使用与C和C++中的变量相同的范围规则创建变量.使用old var
关键字定义的变量具有与Python类似的范围规则.这就是为什么我认为如果我想在这些块之外使用变量,那么变量的初始化应该在块外部进行.
这是一个更复杂的例子
for obj in gen:
# do something with the `obj`
if predicate(obj):
try:
result = f(obj)
except Exception as e:
log(e)
continue
else:
result = g(obj)
# do something useful with the `result`
else:
result = h(obj)
display(result)
Run Code Online (Sandbox Code Playgroud)
我浏览了一些生成器的元素gen
,处理它们并result
在每次迭代时执行一些操作.然后我想用result
循环的最后一个做一些事情.
它是pythonic足以不result
预先分配虚拟值吗?这不会使代码的可读性降低吗?
初始化if
/ else
/ for
/ etc中的变量是否合适?在Python?
Python没有块范围......范围是整个函数,它是完美的pythonic编写
if <condition>:
a = f()
else:
a = g()
Run Code Online (Sandbox Code Playgroud)
如果你想用C++编写然后用C++编写C++,不要用Python编写C++ ......这是个坏主意.
好的,这里有两点需要澄清,这是 python 的基础。
python 中没有变量声明/初始化。类似的表达式a = f(x)
只是将 f 返回的对象命名为的方案a
。该名称a
稍后可用于命名任何其他对象,无论其类型是什么。看这个答案。
python 中的块可以是模块、类或函数的主体。这些对象内定义/命名的任何内容对于后面的代码都是可见的,直到块结束。循环或 if-else 不是块。因此,在循环外部或 if/else 之前定义的任何名称都将在循环内部可见,反之亦然。看到这个。global
和nonlocal
对象略有不同。python 中没有,let
因为这是默认行为。
在您的情况下,唯一关心的是您如何a
在代码中进一步使用。f
如果您的代码需要or返回的对象类型,g
除非出现错误,否则它应该可以正常工作。因为 if 或 else 中至少有一个应该在正常操作中运行,因此a
将引用某种对象(如果 if 和 else 中的名称不同,那将是一个问题)。如果您想确保后续代码不会中断,您可以使用 atry-except-else
捕获函数生成的任何错误,并except
在适当报告/记录错误后为子句中的 a 分配默认值。
因此,总结并直接解决您的问题,为 if-else 语句或循环内的对象分配名称是非常好的做法,前提是:
if 和 else 子句中使用相同的名称,以便保证该名称引用语句末尾的对象。额外的try-except-else
错误捕获可以处理函数引发的异常。
名称不应该太短、通用或不能清楚地表达代码意图的名称a
,res
例如,等等。一个合理的名称将带来更好的可读性,并防止稍后对其他对象意外使用相同的名称,从而丢失原来的。