Python 作用域、函数、块和非本地
Python scope, functions, blocks and non-local
我对范围感到困惑。
如果有的话,分配一个变量 'within a function' 和在一个变量中分配一个变量之间的区别是什么?
缩进块?我读过很多地方说 if 和 try 块没有创建或没有自己的范围,但我也有
读到变量的范围是定义它的最里面的块。
我用谷歌搜索但无法在 if 或 try 块中找到非本地示例。
def sixdig2iso(pathfrom):
os.chdir(pathfrom)
filelist = os.listdir()
nonlocal xfrs
xfrs = 0
PyCharm 表示非局部变量 'xfrs' 必须绑定在外部函数范围内
这不是这个函数的最外层吗?那有什么问题呢?
这个函数的最外层部分 != 是外层函数吗?即使每个函数的作用域与那些相同函数的内部部分不同?!
if xfrs == 0:
restofit = frs[1:]
try:
convert = datetime.strptime(mm, '%m%d%y')
except ValueError as e:
logger.info(f"For {filename}, mm is: {mm} - and the error is: {e}")
count_err += 1
ender = ' '.join(restofit)
fronter = str(convert.date())
PyCharm 说第二个转换 'might' 在赋值前使用
我尝试制作一个内部函数
def sixdig2iso(pathfrom):
"""Converts six digit dates into proper datetime format in place."""
os.chdir(pathfrom)
filelist = os.listdir()
nonlocal xfrs
xfrs = 0
def blockscope():
但是 PyCharm 给了我同样的“非局部变量 'xfrs' 必须绑定在外部函数范围内”警告。
更新
我的回复太长了,无法发表评论。
“我们不得不猜测,因为你没有提供完整的例子”
对于这些问题,我似乎永远无法在“不够”和“太多”信息之间取得平衡。我可能不认为你说的缺失部分是相关的,这首先与我对问题的理解有关。
“无论你在这个函数内部创建了多少个函数嵌套,nonlocal 只向外看。”
看,我不知道。然后我推断,它看起来也只是“向上”,对吧?
“由于 .strptime() 可能因异常而失败,convert 可能最终未被分配值,因为您没有在 try 块之外初始化 convert。 “
好的,很好,这很有帮助。我没有意识到(PyCharm 没有像你刚才那样解释)这就是 PyCharm 所说的。但这也是我对 try 块的“范围”感到困惑的原因。
在您提供的第一个示例中,xfrs
仅在您作为示例提供的函数中定义。我们不得不猜测,因为您没有提供完整的示例,但是来自 PyCharm 的消息表明您没有在另一个函数中定义此函数,该函数中已经定义了这样的标识符并且没有 xfrs
在全局范围内。
在第二个示例中,您分配给 try .. except
块的 try
部分中的 convert
。由于 .strptime()
可能会因异常而失败,因此 convert
可能最终没有被分配一个值,因为您没有在 try
块之外初始化 convert
。因此,PyCharm 是正确的(同样,我们必须假设您没有提供完整的示例。
最后,在第三个示例中,您开始在函数内部定义一个函数,但仍然将 nonlocal
应用于 sixdig2iso()
范围内的变量 - 嵌套多少并不重要你在这个函数中创建的函数,nonlocal
只向外看。
nonlocal
的典型用法是 @Carcigenicate 在其 link 中提供的(此处进行了一些修改):
x = 0
def outer():
x = 1
def inner():
nonlocal x
x += 1
return x
return x, inner
v, f = outer()
print(x, v, f())
outer()
返回的函数在调用时产生2
,因为它的inner()
的非局部变量x
与局部变量[=28]相同=] 的 outer()
,从 1
开始,并在调用函数时添加 1
。
你可以看出这是怎么回事,因为 outer()
返回的值是 1
,但是调用返回的函数 f()
returns 2
.一直以来,全局 x
未被触及。
尝试将 nonlocal
更改为 global
,您会发现结果发生了变化:
0 1 2
收件人:
0 1 1
我希望这有助于解释 nonlocal
的情况。
我对范围感到困惑。 如果有的话,分配一个变量 'within a function' 和在一个变量中分配一个变量之间的区别是什么? 缩进块?我读过很多地方说 if 和 try 块没有创建或没有自己的范围,但我也有 读到变量的范围是定义它的最里面的块。 我用谷歌搜索但无法在 if 或 try 块中找到非本地示例。
def sixdig2iso(pathfrom):
os.chdir(pathfrom)
filelist = os.listdir()
nonlocal xfrs
xfrs = 0
PyCharm 表示非局部变量 'xfrs' 必须绑定在外部函数范围内 这不是这个函数的最外层吗?那有什么问题呢? 这个函数的最外层部分 != 是外层函数吗?即使每个函数的作用域与那些相同函数的内部部分不同?!
if xfrs == 0:
restofit = frs[1:]
try:
convert = datetime.strptime(mm, '%m%d%y')
except ValueError as e:
logger.info(f"For {filename}, mm is: {mm} - and the error is: {e}")
count_err += 1
ender = ' '.join(restofit)
fronter = str(convert.date())
PyCharm 说第二个转换 'might' 在赋值前使用
我尝试制作一个内部函数
def sixdig2iso(pathfrom):
"""Converts six digit dates into proper datetime format in place."""
os.chdir(pathfrom)
filelist = os.listdir()
nonlocal xfrs
xfrs = 0
def blockscope():
但是 PyCharm 给了我同样的“非局部变量 'xfrs' 必须绑定在外部函数范围内”警告。
更新 我的回复太长了,无法发表评论。
“我们不得不猜测,因为你没有提供完整的例子” 对于这些问题,我似乎永远无法在“不够”和“太多”信息之间取得平衡。我可能不认为你说的缺失部分是相关的,这首先与我对问题的理解有关。
“无论你在这个函数内部创建了多少个函数嵌套,nonlocal 只向外看。” 看,我不知道。然后我推断,它看起来也只是“向上”,对吧?
“由于 .strptime() 可能因异常而失败,convert 可能最终未被分配值,因为您没有在 try 块之外初始化 convert。 “ 好的,很好,这很有帮助。我没有意识到(PyCharm 没有像你刚才那样解释)这就是 PyCharm 所说的。但这也是我对 try 块的“范围”感到困惑的原因。
在您提供的第一个示例中,xfrs
仅在您作为示例提供的函数中定义。我们不得不猜测,因为您没有提供完整的示例,但是来自 PyCharm 的消息表明您没有在另一个函数中定义此函数,该函数中已经定义了这样的标识符并且没有 xfrs
在全局范围内。
在第二个示例中,您分配给 try .. except
块的 try
部分中的 convert
。由于 .strptime()
可能会因异常而失败,因此 convert
可能最终没有被分配一个值,因为您没有在 try
块之外初始化 convert
。因此,PyCharm 是正确的(同样,我们必须假设您没有提供完整的示例。
最后,在第三个示例中,您开始在函数内部定义一个函数,但仍然将 nonlocal
应用于 sixdig2iso()
范围内的变量 - 嵌套多少并不重要你在这个函数中创建的函数,nonlocal
只向外看。
nonlocal
的典型用法是 @Carcigenicate 在其 link 中提供的(此处进行了一些修改):
x = 0
def outer():
x = 1
def inner():
nonlocal x
x += 1
return x
return x, inner
v, f = outer()
print(x, v, f())
outer()
返回的函数在调用时产生2
,因为它的inner()
的非局部变量x
与局部变量[=28]相同=] 的 outer()
,从 1
开始,并在调用函数时添加 1
。
你可以看出这是怎么回事,因为 outer()
返回的值是 1
,但是调用返回的函数 f()
returns 2
.一直以来,全局 x
未被触及。
尝试将 nonlocal
更改为 global
,您会发现结果发生了变化:
0 1 2
收件人:
0 1 1
我希望这有助于解释 nonlocal
的情况。