V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
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 · Mar 15, 2023 · 3458 views
    This topic created in 1143 days ago, the information mentioned may be changed or developed.

    今天在看 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 replies    2023-03-15 23:43:31 +08:00
    zhlxsh
        1
    zhlxsh  
       Mar 15, 2023 via iPhone
    局部变量 ch 可能在赋值之前使用

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

    假设我理解没错,语言没有强制规定 for 循环作用域,代码跑起来没问题,编译器报语法错误。 那就是是写的人不规范😂
    KMpAn8Obw1QhPoEP
        2
    KMpAn8Obw1QhPoEP  
       Mar 15, 2023 via Android
    这…你可能没写过 JS ?
    KMpAn8Obw1QhPoEP
        3
    KMpAn8Obw1QhPoEP  
       Mar 15, 2023 via Android
    不对啊 你写过 JS 为啥会叹为观止…ES6 之前不都这样吗
    KMpAn8Obw1QhPoEP
        4
    KMpAn8Obw1QhPoEP  
       Mar 15, 2023 via Android
    直接 var 或者连 var 都不写 就直接在 global 上定义属性才叫叹为观止…
    Aloento
        5
    Aloento  
    OP
       Mar 15, 2023
    @enchilada2020 我是直接从 ES6 开始学的 JS (不如说一来就用的 TS )
    然后写代码一直都是非常的规范,从来没用过黑魔法
    所以说虽然我知道 var 是全局,但是 python 这种连 var / let / := 也不需要的语言
    属实是超出了我的认知范围
    KMpAn8Obw1QhPoEP
        6
    KMpAn8Obw1QhPoEP  
       Mar 15, 2023 via Android
    @Aloento 哈哈 看看 ES6 之前的 JS 那才叫群魔乱舞的感觉 直接写规范 TS 是正确选择😉
    celerysoft
        7
    celerysoft  
       Mar 15, 2023
    如果 len(self.ups) == 0 ,for 循环没有执行,那 ch 就没有赋值,并且直接在 self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False) 这里调用了,所谓的「局部变量 ch 可能在赋值之前使用」说的就是这种情况吧

    不过我有点不理解你吐槽的点,你是觉得 ch 应该在没有声明的情况下就能使用吗?还是说不习惯 Python 没有专门的词用于变量声明
    KMpAn8Obw1QhPoEP
        8
    KMpAn8Obw1QhPoEP  
       Mar 15, 2023 via Android
    @celerysoft 他吐槽的是 Python 没块作用域…
    fantasticfears
        9
    fantasticfears  
       Mar 15, 2023
    Python 没有块作用域。Python 没有块作用域。Python 没有块作用域。
    重要的事情说三遍
    celerysoft
        10
    celerysoft  
       Mar 15, 2023
    @enchilada2020 那我的确没理解 OP 的意思,如果在不知道 Python 没有块作用域的前提下来读这段代码,确实晦涩难懂
    xuanbg
        11
    xuanbg  
       Mar 15, 2023
    这个哪怕是 Java ,也一样会报这个警告。因为你在倒数第二行是用了 ch 变量,如果 self.ups 为空集合,ch 上哪去赋值呢?
    cmdOptionKana
        12
    cmdOptionKana  
       Mar 15, 2023
    Python 的作用域确实是比较与众不同,稍稍有点难用,并且没啥特别优点,我认为算是 Python 设计得比较差的一点。

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

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

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

    应该会抛出 NameError 吧

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

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