今天在看 Hifigan 的源码,突然发现 IDE 提示 ch 变量 warning
    self.resblocks = nn.ModuleList()
    for i in range(len(self.ups)):
      ch = upsample_initial_channel // (2 ** (i + 1))
      for j, (k, d) in enumerate(zip(resblock_kernel_sizes, resblock_dilation_sizes)):
        self.resblocks.append(resblock(ch, k, d))
    self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False)
    self.ups.apply(init_weights)
局部变量 ch 可能在赋值之前使用
首先说明本人不会 python ,今天看到这段百思不得其解
询问 AI 也没问出个所以然,遂询问朋友
得到了这样的回答:
Python 的 for 不认为是作用域
Python 没有语句块的概念
最小作用域就是闭包或者函数
知道这个以后我脑海中只有一句话
真的是令人叹为观止
|      1zhlxsh      2023-03-15 02:34:01 +08:00 via iPhone 局部变量 ch 可能在赋值之前使用 这句话是说,在 for 循环结束后使用了 ch ? 假设我理解没错,语言没有强制规定 for 循环作用域,代码跑起来没问题,编译器报语法错误。 那就是是写的人不规范😂 | 
|  |      2KMpAn8Obw1QhPoEP      2023-03-15 02:50:41 +08:00 via Android 这…你可能没写过 JS ? | 
|  |      3KMpAn8Obw1QhPoEP      2023-03-15 02:51:49 +08:00 via Android 不对啊 你写过 JS 为啥会叹为观止…ES6 之前不都这样吗 | 
|  |      4KMpAn8Obw1QhPoEP      2023-03-15 02:53:16 +08:00 via Android 直接 var 或者连 var 都不写 就直接在 global 上定义属性才叫叹为观止… | 
|  |      5Aloento OP @enchilada2020 我是直接从 ES6 开始学的 JS (不如说一来就用的 TS ) 然后写代码一直都是非常的规范,从来没用过黑魔法 所以说虽然我知道 var 是全局,但是 python 这种连 var / let / := 也不需要的语言 属实是超出了我的认知范围 | 
|  |      6KMpAn8Obw1QhPoEP      2023-03-15 03:02:24 +08:00 via Android @Aloento 哈哈 看看 ES6 之前的 JS 那才叫群魔乱舞的感觉 直接写规范 TS 是正确选择😉 | 
|  |      7celerysoft      2023-03-15 03:19:32 +08:00 如果 len(self.ups) == 0 ,for 循环没有执行,那 ch 就没有赋值,并且直接在 self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False) 这里调用了,所谓的「局部变量 ch 可能在赋值之前使用」说的就是这种情况吧 不过我有点不理解你吐槽的点,你是觉得 ch 应该在没有声明的情况下就能使用吗?还是说不习惯 Python 没有专门的词用于变量声明 | 
|  |      8KMpAn8Obw1QhPoEP      2023-03-15 03:25:17 +08:00 via Android @celerysoft 他吐槽的是 Python 没块作用域… | 
|  |      9fantasticfears      2023-03-15 03:43:15 +08:00 Python 没有块作用域。Python 没有块作用域。Python 没有块作用域。 重要的事情说三遍 | 
|  |      10celerysoft      2023-03-15 04:24:22 +08:00 @enchilada2020 那我的确没理解 OP 的意思,如果在不知道 Python 没有块作用域的前提下来读这段代码,确实晦涩难懂 | 
|  |      11xuanbg      2023-03-15 07:58:11 +08:00 这个哪怕是 Java ,也一样会报这个警告。因为你在倒数第二行是用了 ch 变量,如果 self.ups 为空集合,ch 上哪去赋值呢? | 
|  |      12cmdOptionKana      2023-03-15 08:18:14 +08:00 Python 的作用域确实是比较与众不同,稍稍有点难用,并且没啥特别优点,我认为算是 Python 设计得比较差的一点。 但日常使用也没啥大问题就是了。 | 
|      13cbdyzj      2023-03-15 08:21:29 +08:00 Python 没有块作用域,C 、C++、Java 、JavaScript 、C#、Rust 等主流语言都支持块作用域,PO 不清楚实属正常 楼上说 ES3 也不支持块作用域的,现在是 2023 年 | 
|  |      14darkengine      2023-03-15 08:42:33 +08:00 @xuanbg 换 Java 直接就编不过了 | 
|  |      15xuanbg      2023-03-15 09:01:01 +08:00 @darkengine 可以过的。但我怀疑 OP 贴的代码中最后两行代码的缩进不对,应该加两个空格,这样就不会有这个警告。并且,变量在使用逻辑上也能和上面的循环对应起来。 | 
|  |      17raymanr      2023-03-15 09:15:42 +08:00 这个还比较好理解吧, 如果 len(self.ups) == 0 那么循环就不会执行, 那么就会出现 ch 没有出现初始化的情况, 应该会抛出 NameError 吧 在循环前给 ch 一个初始化的值是更合理的做法 这个是作者写得不规范的问题, 和 let var 之类的声明语句没关系, 反正没有声明也检查出这个问题了嘛 | 
|      18bl4ckoooooH4t      2023-03-15 09:17:36 +08:00 在 for i in range(len(self.ups)): 里面定义了 ch , 如果 len(self.ups) == 0 , 那么 ch 变量就不会被定义,这样就引用了未定义的变量。 应该是这样吧 | 
|      19fbichijing      2023-03-15 09:39:31 +08:00 平时写的时候好像倒没怎么在意这个问题。只是乍一看起来代码感觉好像不太自然。如果是我自己在写的话可能在 for 前面给 ch 初始化一下。 好像许多编程语言 for 里面的局部变量都无法在 for 之外调用,如果 Python 确实这么做也可以的话,反而说明了使用变量前初始化的必要性。万一使用了一个自己前面定义过的变量,但是自己不记得了,这就会出现难以调试的 bug. | 
|      20pendulum      2023-03-15 10:10:37 +08:00 for 循环之前应该先初始化 ch ,因为 for 循环后又用到了 ch 。或者给 for 循环里面的 ch 加个 nonlocal | 
|  |      21proxytoworld      2023-03-15 10:56:00 +08:00 因为 python 不确定是不是一定进入 for 循环里面赋值(猜测)所以才会报这个错,如果你确保一定会进入的话可以忽略这个,毕竟编译器比较死板 | 
|  |      22KMpAn8Obw1QhPoEP      2023-03-15 11:11:01 +08:00 via Android @proxytoworld 这样做等于在埋坑 半年后你会忘了这个在代码里体现不出来的隐藏默认条件 之后如果因为某种原因这个条件被破坏了 那就是炸弹 | 
|  |      23raymanr      2023-03-15 11:11:39 +08:00 @enchilada2020 我多年以前自学 js 的时候看到这里都吐了, 但凡变量名写错, 就变成了全局变量真的吐了, 加上其他各类坑问题风骚语法, 以至于很长时间里 javascript 在我眼里就是混乱邪恶的语言代表....... 即便现在好了很多, js 这东西还是让我觉得能不碰就不碰的好 | 
|  |      24KMpAn8Obw1QhPoEP      2023-03-15 11:24:21 +08:00 via Android @raymanr 是很恶心 哈哈 偏偏它成了 Web 领域避不开的语言🤣 | 
|      25whileFalse      2023-03-15 23:43:31 +08:00 via iPhone 这不很正常吗,你 for 循环不一定会跑啊 万一 self.ups 是空数组呢 |