V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Aloento
V2EX  ›  Python

一个关于作用域的吐槽

  •  1
     
  •   Aloento · 2023-03-15 02:08:00 +08:00 · 2673 次点击
    这是一个创建于 603 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天在看 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 没有语句块的概念

    最小作用域就是闭包或者函数

    知道这个以后我脑海中只有一句话

    真的是令人叹为观止

    25 条回复    2023-03-15 23:43:31 +08:00
    zhlxsh
        1
    zhlxsh  
       2023-03-15 02:34:01 +08:00 via iPhone
    局部变量 ch 可能在赋值之前使用

    这句话是说,在 for 循环结束后使用了 ch ?

    假设我理解没错,语言没有强制规定 for 循环作用域,代码跑起来没问题,编译器报语法错误。 那就是是写的人不规范😂
    enchilada2020
        2
    enchilada2020  
       2023-03-15 02:50:41 +08:00 via Android
    这…你可能没写过 JS ?
    enchilada2020
        3
    enchilada2020  
       2023-03-15 02:51:49 +08:00 via Android
    不对啊 你写过 JS 为啥会叹为观止…ES6 之前不都这样吗
    enchilada2020
        4
    enchilada2020  
       2023-03-15 02:53:16 +08:00 via Android
    直接 var 或者连 var 都不写 就直接在 global 上定义属性才叫叹为观止…
    Aloento
        5
    Aloento  
    OP
       2023-03-15 03:00:39 +08:00
    @enchilada2020 我是直接从 ES6 开始学的 JS (不如说一来就用的 TS )
    然后写代码一直都是非常的规范,从来没用过黑魔法
    所以说虽然我知道 var 是全局,但是 python 这种连 var / let / := 也不需要的语言
    属实是超出了我的认知范围
    enchilada2020
        6
    enchilada2020  
       2023-03-15 03:02:24 +08:00 via Android
    @Aloento 哈哈 看看 ES6 之前的 JS 那才叫群魔乱舞的感觉 直接写规范 TS 是正确选择😉
    celerysoft
        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 没有专门的词用于变量声明
    enchilada2020
        8
    enchilada2020  
       2023-03-15 03:25:17 +08:00 via Android
    @celerysoft 他吐槽的是 Python 没块作用域…
    fantasticfears
        9
    fantasticfears  
       2023-03-15 03:43:15 +08:00
    Python 没有块作用域。Python 没有块作用域。Python 没有块作用域。
    重要的事情说三遍
    celerysoft
        10
    celerysoft  
       2023-03-15 04:24:22 +08:00
    @enchilada2020 那我的确没理解 OP 的意思,如果在不知道 Python 没有块作用域的前提下来读这段代码,确实晦涩难懂
    xuanbg
        11
    xuanbg  
       2023-03-15 07:58:11 +08:00
    这个哪怕是 Java ,也一样会报这个警告。因为你在倒数第二行是用了 ch 变量,如果 self.ups 为空集合,ch 上哪去赋值呢?
    cmdOptionKana
        12
    cmdOptionKana  
       2023-03-15 08:18:14 +08:00
    Python 的作用域确实是比较与众不同,稍稍有点难用,并且没啥特别优点,我认为算是 Python 设计得比较差的一点。

    但日常使用也没啥大问题就是了。
    cbdyzj
        13
    cbdyzj  
       2023-03-15 08:21:29 +08:00
    Python 没有块作用域,C 、C++、Java 、JavaScript 、C#、Rust 等主流语言都支持块作用域,PO 不清楚实属正常
    楼上说 ES3 也不支持块作用域的,现在是 2023 年
    darkengine
        14
    darkengine  
       2023-03-15 08:42:33 +08:00
    @xuanbg 换 Java 直接就编不过了
    xuanbg
        15
    xuanbg  
       2023-03-15 09:01:01 +08:00
    @darkengine 可以过的。但我怀疑 OP 贴的代码中最后两行代码的缩进不对,应该加两个空格,这样就不会有这个警告。并且,变量在使用逻辑上也能和上面的循环对应起来。
    hsfzxjy
        16
    hsfzxjy  
       2023-03-15 09:05:44 +08:00 via Android
    @xuanbg 缩进是对的,代码就是这样,相当于一种取巧的方式获得 ch 最后一个计算结果
    raymanr
        17
    raymanr  
       2023-03-15 09:15:42 +08:00
    这个还比较好理解吧,

    如果 len(self.ups) == 0 那么循环就不会执行,

    那么就会出现 ch 没有出现初始化的情况,

    应该会抛出 NameError 吧

    在循环前给 ch 一个初始化的值是更合理的做法

    这个是作者写得不规范的问题, 和 let var 之类的声明语句没关系, 反正没有声明也检查出这个问题了嘛
    bl4ckoooooH4t
        18
    bl4ckoooooH4t  
       2023-03-15 09:17:36 +08:00
    在 for i in range(len(self.ups)): 里面定义了 ch , 如果 len(self.ups) == 0 , 那么 ch 变量就不会被定义,这样就引用了未定义的变量。 应该是这样吧
    fbichijing
        19
    fbichijing  
       2023-03-15 09:39:31 +08:00
    平时写的时候好像倒没怎么在意这个问题。只是乍一看起来代码感觉好像不太自然。如果是我自己在写的话可能在 for 前面给 ch 初始化一下。
    好像许多编程语言 for 里面的局部变量都无法在 for 之外调用,如果 Python 确实这么做也可以的话,反而说明了使用变量前初始化的必要性。万一使用了一个自己前面定义过的变量,但是自己不记得了,这就会出现难以调试的 bug.
    pendulum
        20
    pendulum  
       2023-03-15 10:10:37 +08:00
    for 循环之前应该先初始化 ch ,因为 for 循环后又用到了 ch 。或者给 for 循环里面的 ch 加个 nonlocal
    proxytoworld
        21
    proxytoworld  
       2023-03-15 10:56:00 +08:00
    因为 python 不确定是不是一定进入 for 循环里面赋值(猜测)所以才会报这个错,如果你确保一定会进入的话可以忽略这个,毕竟编译器比较死板
    enchilada2020
        22
    enchilada2020  
       2023-03-15 11:11:01 +08:00 via Android
    @proxytoworld 这样做等于在埋坑 半年后你会忘了这个在代码里体现不出来的隐藏默认条件 之后如果因为某种原因这个条件被破坏了 那就是炸弹
    raymanr
        23
    raymanr  
       2023-03-15 11:11:39 +08:00
    @enchilada2020 我多年以前自学 js 的时候看到这里都吐了, 但凡变量名写错, 就变成了全局变量真的吐了, 加上其他各类坑问题风骚语法, 以至于很长时间里 javascript 在我眼里就是混乱邪恶的语言代表....... 即便现在好了很多, js 这东西还是让我觉得能不碰就不碰的好
    enchilada2020
        24
    enchilada2020  
       2023-03-15 11:24:21 +08:00 via Android
    @raymanr 是很恶心 哈哈 偏偏它成了 Web 领域避不开的语言🤣
    whileFalse
        25
    whileFalse  
       2023-03-15 23:43:31 +08:00 via iPhone
    这不很正常吗,你 for 循环不一定会跑啊 万一 self.ups 是空数组呢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3004 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 13:26 · PVG 21:26 · LAX 05:26 · JFK 08:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.