最近学 Python ,关于作用域的问题有点不明白 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
dwlovelife
V2EX    程序员

最近学 Python ,关于作用域的问题有点不明白

  •  
  •   dwlovelife 2021-12-16 14:55:34 +08:00 3206 次点击
    这是一个创建于 1399 天前的主题,其中的信息可能已经有所发展或是发生改变。
    def foo(): c = "hello" x = 0 def bar(): b = True print(a) print(b) print(c) x = a bar() print(x) if __name__ == "__main__": a = 100 foo() 

    结果就是: 100 True hello 0

    问题 1: 为什么在 bar 函数内能访问 a 呢 问题 2: 能访问按道理能赋值啊,x 咋还是 0

    22 条回复    2022-03-03 17:21:50 +08:00
    jxxz
        1
    jxxz  
       2021-12-16 15:06:42 +08:00   2
    a 相当于全局变量
    x = a 的作用是创建一个局部变量 x ,这个 x 是 bar 内部的 x 不是 foo 里的 x ,你要用 foo 里的 x 要加上 nonlocal
    rglee
        2
    rglee  
       2021-12-16 15:09:13 +08:00 via Android   3
    此 x 非彼 x ,用 id()看一下?
    ipwx
        3
    ipwx  
       2021-12-16 15:10:58 +08:00   1
    如果你在 foo 里面 a = 200 ,然后在 foo() 之后 print(a),你会发现 foo 里面的 a 和外面的 a 就不是一个 a 了。

    我觉得这是 Python 让人不满意的地方。因为没有声明,赋值即声明,所以会搞不清楚作用域。

    事实上如果你运行如下代码:

    def main():
    ....print(a)
    ....a = 1

    a = 2
    main()

    你会得到一个异常:

    UnboundLocalError: local variable 'a' referenced before assignment

    原因是 a = 1 这句话在 main 函数里面定义了一个变量 a ,因此你在 print(a) 这一行就引用不到全局的 a 了。
    ddmasato
        4
    ddmasato  
       2021-12-16 15:52:37 +08:00   1
    赋值即重新定义, 所以 bar 里面的 x 是在 bar 作用域中的 x,不会影响到 foo 中的 x
    foobear
        5
    foobear  
       2021-12-16 16:05:16 +08:00   5
    https://pythontutor.com/visualize.html 把你的代码复制到上面跑一遍就明白了
        6
    Skiro  
       2021-12-16 17:20:05 +08:00 via Android   1
    问题 1: 为什么在 bar 函数内能访问 a 呢
    回答:因为 a 是全局变量。
    问题 2: 能访问按道理能赋值啊,x 咋还是 0
    回答:因为实际上赋值成功的是 bar()里的 x ,这里 x ==100 ,而你输出的是 foo()里的 x 。
    jaredyam
        7
    jaredyam  
       2021-12-16 17:40:56 +08:00   1
    前几层已经说得很明白的,问题 2 也不是 Python 的问题。
    AV1
        8
    AV1  
       2021-12-16 18:19:46 +08:00 via Android   1
    python 里,等号不仅有赋值的作用,还有声明变量的作用,相当于 JS 的 var 。
    比如 x=a ,其实干了两件事情,一是在当前作用域声明了一个叫 x 的变量,二是赋值为 a 。
    只要声明了变量,当前作用域内无论哪个位置,都再也不能访问外部的同名变量。
    ch2
        9
    ch2  
       2021-12-16 18:30:01 +08:00   1
    bar 可以访问 foo 里的 x,但是 bar 里直接修改 x 不行
    ila
        10
    ila  
       2021-12-16 18:35:35 +08:00 via Android   1
    用类或全局变量
    vance123
        11
    vance123  
       2021-12-16 19:00:15 +08:00 via Android   2
    是有意设计成这样的
    函数引用自己作用域内不存在的变量时,可以报错,也可以顺着词法环境往上搜索,python 选择了后者。
    函数在内部赋值时,可以选择对已有变量赋值,或者重新定义一个变量,python 选择了后者。
    原则是选择最合乎逻辑的那一个方案
    flyhelan
        12
    flyhelan  
       2021-12-16 19:02:57 +08:00   1
    不如 在 x = a 后 再加一行 print(x) 你体会一下。bar 里的 x 和 foo 里的 x 不是同一个 x 。

    def foo():
    c = "hello"
    x = 0
    def bar():
    b = True
    print(a)
    print(b)
    print(c)
    x = a
    print(x)
    bar()
    print(x)


    if __name__ == "__main__":
    a = 100
    foo()
    Buges
        13
    Buges  
       2021-12-16 19:10:11 +08:00 via Android   1
    @ipwx 我觉得这个反而是挺好的设计,explicitly mutate global 。
    kidblg
        14
    kidblg  
       2021-12-16 19:15:47 +08:00   1
    进入 foo 之前,产生的作用域 1 内:a=100
    进入 foo 后,产生的作用域 2 内:c=hello, x=0 ,而且因为函数内可以访问函数外的变量,所以可以访问 a=100
    进入 bar 时,产生的作用域 3 内:b=true, x=a ,但 bar 退出时,就销毁这个新的作用域

    所以 x 是 100
    rationa1cuzz
        15
    rationa1cuzz  
       2021-12-16 19:26:09 +08:00   1
    关键词:作用域,局部变量与全局变量
    拓展:形参 实参
    xiaoxinshiwo
        16
    xiaoxinshiwo  
       2021-12-16 19:26:29 +08:00   1
    @foobear
    powerman
        17
    powerman  
       2021-12-16 19:32:49 +08:00   1
    懒得很,我从来都是把所有语言当成 类 C 语言的风格来写,根本不关心变量作用域
    inframe
        18
    inframe  
       2021-12-16 22:09:57 +08:00
    python 变量搜索顺序是 LEGB,
    https://www.cnblogs.com/xuexianqi/p/13658528.html
    zhaohehedola
        19
    zhaohehedola  
       2021-12-16 22:56:56 +08:00 via iPhone
    外层变量 可读不可写
    echoechoin
        20
    echoechoin  
       2021-12-17 10:04:11 +08:00
    闭包
    NanFengXiangWan
        21
    NanFengXiangWan  
       2021-12-17 12:24:48 +08:00
    因为变量 a 是全局作用域
    ![屏幕截图 2021-12-17 122430.png]( https://nf-1252257903.cos.ap-chengdu.myqcloud.com/2021/12/17/1a7583baaf637.png)
    flyhelan
        22
    flyhelan  
       2022-03-03 17:21:50 +08:00
    <section id="nice" data-tool="mdnice 编辑器" data-website="https://www.mdnice.com" style="font-size: 16px; color: black; padding: 0 10px; line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; word-break: break-word; word-wrap: break-word; text-align: left; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;"><pre class="custom" data-tool="mdnice 编辑器" style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block; background: url( https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">def</span>&nbsp;<span class="hljs-title" style="color: #61aeee; line-height: 26px;">foo</span><span class="hljs-params" style="line-height: 26px;">()</span>:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;<span class="hljs-string" style="color: #98c379; line-height: 26px;">"hello"</span><br>&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;<span class="hljs-number" style="color: #d19a66; line-height: 26px;">0</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">def</span>&nbsp;<span class="hljs-title" style="color: #61aeee; line-height: 26px;">bar</span><span class="hljs-params" style="line-height: 26px;">()</span>:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;=&nbsp;<span class="hljs-literal" style="color: #56b6c2; line-height: 26px;">True</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(a)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(b)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(c)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;a<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(x)&nbsp;<span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">#&nbsp;新增这条</span><br>&nbsp;&nbsp;&nbsp;&nbsp;bar()<br>&nbsp;&nbsp;&nbsp;&nbsp;print(x)<br><br><br><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">if</span>&nbsp;__name__&nbsp;==&nbsp;<span class="hljs-string" style="color: #98c379; line-height: 26px;">"__main__"</span>:<br>&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;=&nbsp;<span class="hljs-number" style="color: #d19a66; line-height: 26px;">100</span><br>&nbsp;&nbsp;&nbsp;&nbsp;foo()<br></code></pre>
    </section>
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     873 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 20:58 PVG 04:58 LAX 13:58 JFK 16:58
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86