Python中while循环和for循环的区别是什么?写带参数的装饰器时用while获取不到参数但用for可以

环境 python3.6.2

代码 gist

把情景写错最简化的 demo 丢在 gist 上了. 只有 gistfile2.py 用 for 循环是能跑通的, 1 和 3 是用 while 做循环都提示那个参数未定义, 表现为代码一进入 while 代码块立马就失去了这个变量, 在 while 之前还是能获取到.

查资料查了半天没查出什么区别, 搜 difference between while and for 搜出一打入门教程. 所有文章都说 while 和 for 只有表现区别没有深层区别, 编译后结果是一样的. 那么我遇到的这个什么情况.


Python中while循环和for循环的区别是什么?写带参数的装饰器时用while获取不到参数但用for可以

9 回复

不要 retry_time -= 1


这个问题其实挺有意思的,它把两个看似不相关的东西联系起来了。我来拆开说一下。

while和for的核心区别

  • while 就是个条件判断循环,只要条件为True就一直跑
  • for 是迭代器循环,用来遍历可迭代对象(列表、元组、字典、字符串等)
# while示例 - 手动控制循环
count = 0
while count < 5:
    print(count)
    count += 1

# for示例 - 自动迭代
for i in range(5):
    print(i)

关于装饰器参数的问题: 你说的情况我猜是这样 - 在装饰器工厂函数里,用while遍历参数时可能遇到了无限循环或者提前退出的问题,而for能正确处理参数列表。

看个具体例子:

def decorator_with_args(*args):
    def actual_decorator(func):
        # 用for可以正确遍历args
        for arg in args:
            print(f"装饰器参数: {arg}")
        
        # 如果用while可能会这样写,但容易出错
        # i = 0
        # while i < len(args):  # 需要手动维护索引
        #     print(args[i])
        #     i += 1
        
        def wrapper(*func_args):
            return func(*func_args)
        return wrapper
    return actual_decorator

@decorator_with_args("param1", "param2", "param3")
def my_function():
    print("函数执行")

my_function()

关键点

  • for循环更适合处理已知的、有限的可迭代对象
  • while更适合不确定次数的循环,需要手动控制循环条件
  • 在装饰器参数处理这种场景下,for更简洁安全,while需要额外处理索引和边界条件

简单说就是:for是"遍历已有数据",while是"满足条件就继续"。

不知道为什么, 但可以在条件外部重新定义 retry_time。 下面逻辑可以跑通, 如果你知道原因也请告诉我一下。。doge)

python<br># -*- coding: utf-8 -*-<br>import time<br>from functools import wraps<br><br><br>def retry(retry_time=10):<br> def retry_decorator(func):<br> (func)<br> def wrapper(*args, **kwargs):<br> result = func(*args, **kwargs)<br> n = retry_time<br> while result is None and n &gt;= 0:<br> result = func(*args, **kwargs)<br> time.sleep(0.5)<br> n -= 1<br> return result<br><br> return wrapper<br><br> return retry_decorator<br><br><br>(5)<br>def test(a, b=1):<br> print(a, b)<br> return None<br><br><br>if __name__ == '__main__':<br> test(4)<br>

参考:
https://stackoverflow.com/questions/39990133/while-loop-unboundlocalerror-local-variable-referenced-before-assignment

不赞同你的看法,我认为是:
If you want to simply access a global variable you just use its name. However to change its value you need to use the global keyword.

感谢两位的提醒, 的确是是因为全局变量在代码中重新绑定被视为局部变量的原因. 之前我也想到过这个问题, 但是在 while True 上一行能 print(retry_time)成功, 所以 pass 了这种可能性.
现在无论是声明 nolocal retry_time 还是 inner_retry_time = copy.deepcopy(retry_time), 确定 retry_time 不会在下方代码中重新绑定, 就可以跑通.

要搞清楚,不是全局变量 ,是自由变量
好好看闭包的说明

流畅的 Python 7.5 7.6 讲了闭包和 nolocal 的使用,我觉得讲的不错,你可以去看看。7.4 讲了变量作用域规则,其中提到了,Python 不要求声明变量,但是假定在函数定义体中赋值的变量是局部变量,这也是你报错 retry_time 未定义的原因。因为代码下方对他进行了赋值,所以 Python 认定他是局部变量,而你在局部变量未被赋值前引用了他。

回到顶部