为什么Python lint要求我使用不同的局部变量名而不是全局变量名

时间:2021-08-20 08:50:25

Given Python code such as

给定Python代码如

def func():
    for i in range(10):
        pass

for i in range(10):
    pass  

pylint complains

pylint抱怨

Redefining name 'i' from outer scope 

What is the Pythonic way to write the above? Use a different variable locally, say j?

什么是Pythonic写上面的方法?在本地使用不同的变量,比如j?

But why, when the variable means exactly the same in both cases (i for index). Let's say I change all local indexes to j and then later I find I want to use j as the second index in the glocal scope. Have to change again?

但是,为什么,当变量在两种情况下都意味着完全相同(i代表索引)。假设我将所有本地索引更改为j,然后我发现我想使用j作为glocal范围中的第二个索引。要改变一下吗?

I can't disable lint warnings, I don't want to have them, I want to write Pythonic, and yet I want to use the same name for the same thing throughout, in the simple case like the above. Is this not possible?

我不能禁用lint警告,我不想拥有它们,我想写Pythonic,但我想在同样的事情中使用相同的名称,在上面的简单情况下。这不可能吗?

3 个解决方案

#1


0  

The linter warns because i lives on after the loop, if it ran at least once. This means that if you were to use it without re-initializing it it would still have the value it had during the last iteration of the loop.

如果它至少运行一次,那么linter警告因为我在循环之后继续生活。这意味着如果您在不重新初始化的情况下使用它,它仍将具有在循环的最后一次迭代期间具有的值。

The way you use it is fine since i will always be reinitialized.

你使用它的方式很好,因为我将永远重新初始化。

A useful practice could be to name all values in the outer scope in ALL_CAPS. This way no mistakes could be made.

一个有用的做法可能是在ALL_CAPS中命名外部作用域中的所有值。这样就不会犯错误。

#2


25  

You can avoid global variable conflict by not having any global variables:

您可以通过不使用任何全局变量来避免全局变量冲突:

def func():
    for i in range(10):
        pass

def _init_func():
    for i in range(10):
        pass  

_init_func()

Any code that needs to run at module-init time can be put into a single function. This leaves, as the only executable code to run during module init: def statements, class statements, and one function call.

任何需要在模块初始化时运行的代码都可以放在一个函数中。这留下了作为模块init期间运行的唯一可执行代码:def语句,类语句和一个函数调用。

Similarly, if your code is not intended to be imported, but rather is a script to be run,

同样,如果您的代码不是要导入的,而是要运行的脚本,

def func():
    for i in range(10):
        pass

def main():
    for i in range(10):
        pass  

if __name__=="__main__":
    main()

#3


2  

Because it eliminate the risk of being using one when you believe you are using the other. Lint tools are made to make your code more robust. By having all your variables having different names, you ensure that no such conflict could arise.

因为当你相信你正在使用另一个时,它可以消除使用它的风险。 Lint工具可以使您的代码更加健壮。通过使所有变量具有不同的名称,可以确保不会出现此类冲突。

This is especially critical in interpreted language because the errors are not checked at "compile time". I once had the problem that the second call to a function gave me an error, because I renamed a function and I didn't realize that in some case There was a variable which was created with the same name as my function, and so, when I was trying to call my function, the interpreter tried to "call" my newly created variable, which never worked XD.

这在解释语言中尤其重要,因为在“编译时”不会检查错误。我曾经遇到过第二次调用函数给我一个错误的问题,因为我重命名了一个函数而我没有意识到在某些情况下有一个变量是用我的函数创建的,所以,当我试图调用我的函数时,解释器试图“调用”我新创建的变量,它从未使用过XD。

this lint policy will avoid that kind of problem.

这种棉绒政策将避免这种问题。

Here is a sample code (this is a program to compute pi) :

这是一个示例代码(这是一个计算pi的程序):

from fractions import Fraction


def order(x):
    r, old_r, n, old_n = 2, 1, 1, 0
    while (x>=r):
        r, old_r, n, old_n = r*r, r, 2*n, n
    return order(x >> old_n) + old_n if old_n > 0 else 0


def term(m, n, i):
    return Fraction(4 * m, n**(2*i+1) * (2*i+1))


def terms_generator(exp_prec):
    ws = [ [term(parm[1], parm[2], 0), 0] + list(parm)
          for parm in ((1, 44, 57),
                       (1, 7, 239),
                       (-1, 12, 682),
                       (1, 24, 12943))]
    digits = 0
    while digits<exp_prec:
        curws = max(ws, key=lambda col: col[0])
        digits = int(0.30103 *
                     (order(curws[0].denominator))
                      - order(curws[0].numerator))
        yield curws[2] * curws[0], digits
        curws[2] = -curws[2]                
        curws[1] += 1
        curws[0] = term(curws[3], curws[4], curws[1])

expected_precision = 1000
pi = 0
for term, dgts in terms_generator(expected_precision):
    pi += term

print("{} digits".format(dgts))
print("pi = 3.{}".format(int((pi-3)*10**expected_precision)))

In this case, I initialized a variable from a generator and the generator used another function which conflicted with my variable name once it was initialized by my generator. Well, It's not a very good example because here both names are global, but from it's structure, it wasn't immediately obvious that it would happen.

在这种情况下,我从生成器初始化了一个变量,并且生成器使用了另一个函数,该函数在我的生成器初始化后与我的变量名冲突。嗯,这不是一个很好的例子,因为这两个名字都是全局的,但从它的结构来看,它不会立即显现出来。

My point is that even if you KNOW how to program, you make mistakes and those practices will help reduce the risks for those to stay hidden.

我的观点是,即使你知道如何编程,你也会犯错误,这些做法将有助于降低那些隐藏的风险。

#1


0  

The linter warns because i lives on after the loop, if it ran at least once. This means that if you were to use it without re-initializing it it would still have the value it had during the last iteration of the loop.

如果它至少运行一次,那么linter警告因为我在循环之后继续生活。这意味着如果您在不重新初始化的情况下使用它,它仍将具有在循环的最后一次迭代期间具有的值。

The way you use it is fine since i will always be reinitialized.

你使用它的方式很好,因为我将永远重新初始化。

A useful practice could be to name all values in the outer scope in ALL_CAPS. This way no mistakes could be made.

一个有用的做法可能是在ALL_CAPS中命名外部作用域中的所有值。这样就不会犯错误。

#2


25  

You can avoid global variable conflict by not having any global variables:

您可以通过不使用任何全局变量来避免全局变量冲突:

def func():
    for i in range(10):
        pass

def _init_func():
    for i in range(10):
        pass  

_init_func()

Any code that needs to run at module-init time can be put into a single function. This leaves, as the only executable code to run during module init: def statements, class statements, and one function call.

任何需要在模块初始化时运行的代码都可以放在一个函数中。这留下了作为模块init期间运行的唯一可执行代码:def语句,类语句和一个函数调用。

Similarly, if your code is not intended to be imported, but rather is a script to be run,

同样,如果您的代码不是要导入的,而是要运行的脚本,

def func():
    for i in range(10):
        pass

def main():
    for i in range(10):
        pass  

if __name__=="__main__":
    main()

#3


2  

Because it eliminate the risk of being using one when you believe you are using the other. Lint tools are made to make your code more robust. By having all your variables having different names, you ensure that no such conflict could arise.

因为当你相信你正在使用另一个时,它可以消除使用它的风险。 Lint工具可以使您的代码更加健壮。通过使所有变量具有不同的名称,可以确保不会出现此类冲突。

This is especially critical in interpreted language because the errors are not checked at "compile time". I once had the problem that the second call to a function gave me an error, because I renamed a function and I didn't realize that in some case There was a variable which was created with the same name as my function, and so, when I was trying to call my function, the interpreter tried to "call" my newly created variable, which never worked XD.

这在解释语言中尤其重要,因为在“编译时”不会检查错误。我曾经遇到过第二次调用函数给我一个错误的问题,因为我重命名了一个函数而我没有意识到在某些情况下有一个变量是用我的函数创建的,所以,当我试图调用我的函数时,解释器试图“调用”我新创建的变量,它从未使用过XD。

this lint policy will avoid that kind of problem.

这种棉绒政策将避免这种问题。

Here is a sample code (this is a program to compute pi) :

这是一个示例代码(这是一个计算pi的程序):

from fractions import Fraction


def order(x):
    r, old_r, n, old_n = 2, 1, 1, 0
    while (x>=r):
        r, old_r, n, old_n = r*r, r, 2*n, n
    return order(x >> old_n) + old_n if old_n > 0 else 0


def term(m, n, i):
    return Fraction(4 * m, n**(2*i+1) * (2*i+1))


def terms_generator(exp_prec):
    ws = [ [term(parm[1], parm[2], 0), 0] + list(parm)
          for parm in ((1, 44, 57),
                       (1, 7, 239),
                       (-1, 12, 682),
                       (1, 24, 12943))]
    digits = 0
    while digits<exp_prec:
        curws = max(ws, key=lambda col: col[0])
        digits = int(0.30103 *
                     (order(curws[0].denominator))
                      - order(curws[0].numerator))
        yield curws[2] * curws[0], digits
        curws[2] = -curws[2]                
        curws[1] += 1
        curws[0] = term(curws[3], curws[4], curws[1])

expected_precision = 1000
pi = 0
for term, dgts in terms_generator(expected_precision):
    pi += term

print("{} digits".format(dgts))
print("pi = 3.{}".format(int((pi-3)*10**expected_precision)))

In this case, I initialized a variable from a generator and the generator used another function which conflicted with my variable name once it was initialized by my generator. Well, It's not a very good example because here both names are global, but from it's structure, it wasn't immediately obvious that it would happen.

在这种情况下,我从生成器初始化了一个变量,并且生成器使用了另一个函数,该函数在我的生成器初始化后与我的变量名冲突。嗯,这不是一个很好的例子,因为这两个名字都是全局的,但从它的结构来看,它不会立即显现出来。

My point is that even if you KNOW how to program, you make mistakes and those practices will help reduce the risks for those to stay hidden.

我的观点是,即使你知道如何编程,你也会犯错误,这些做法将有助于降低那些隐藏的风险。