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