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
cnaol
V2EX  ›  Python

[ Python ]求教大佬关于 locals()动态生成变量

  •  
  •   cnaol · 2018-01-06 19:30:41 +08:00 · 4184 次点击
    这是一个创建于 2512 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在函数外一切使用正常

    #生产变量如 lis0 lis1 默认空列表 并打印出来
    for i in range(0,11):
    locals()['lis%d' % i] = []
    print('lis%d : %s' % (i,eval('lis%d' % i)))

    #单独给变量 lis3 append(6)
    lis3.append(6)

    #全部变量 append(2)打印 lis0~lis10 变量
    for i in range(0,11):
    eval('lis%d' % i).append(2)
    print('lis%d : %s' % (i,eval('lis%d' % i)))

    但是把他包裹在函数中使用
    def func():
    上面的代码
    func()
    在 lis3.append(6)这里就报错:变量名没定义

    但是当我使用 eval('list3').append(6)就正常了




    想请问是为什么以及该如何解决 谢谢
    12 条回复    2018-01-08 12:01:43 +08:00
    ballshapesdsd
        1
    ballshapesdsd  
       2018-01-06 19:47:11 +08:00
    你这种写法,用个 list 不好吗?我看你是在刁难我胖虎
    ballshapesdsd
        2
    ballshapesdsd  
       2018-01-06 20:00:25 +08:00
    你试试把 locals 改成 globals 可以跑出来,或者在函数外面定义一个 lis3,也不会报错,但是结果有问题。只能说 lis3 不完全等于 eval('lis3')
    ballshapesdsd
        4
    ballshapesdsd  
       2018-01-06 20:26:38 +08:00
    https://docs.python.org/2/library/functions.html?highlight=locals#locals
    Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
    官方建议不要修改 locals
    cnaol
        5
    cnaol  
    OP
       2018-01-06 21:05:08 +08:00
    @ballshapesdsd 我试过 globals 确实可以跑出来 但是这样是全局的变量 容易造成污染 谢谢你的回答
    xpresslink
        6
    xpresslink  
       2018-01-06 23:02:34 +08:00
    通常的 Python 实现中,locals()返回的只是菊部变量字典的 copy,和 globals()不一样的。
    在 python 中变量只是对象的标签,只是引用而已,所以你这么蛋疼的需求并无什么实质意义。
    老老实实用个 list 或 dict 就行了,引用起来更方便。
    要是实在想这么弄,还非要搞菊部的。
    直接 exec('lis%s=[]' % i )
    lrxiao
        7
    lrxiao  
       2018-01-07 00:26:21 +08:00
    很简单
    locals 修改的是当前栈帧
    但是 bytecode 这里用到的 lis3 是引用的函数的__code__.co_names / LOAD_GLOBAL
    况且本来就不该修改 locals
    albert2x
        8
    albert2x  
       2018-01-07 02:28:52 +08:00 via iPhone
    试试深拷贝
    introom
        9
    introom  
       2018-01-07 11:09:23 +08:00
    =locals= is different in that the underlying implementation is not based on hash dict. instead, for speed purpose, it's stored as a c array associated with the frame object. cf. https://github.com/python/cpython/blob/master/Python/ceval.c#L878 for a clear picture. I don't recommend modifying the local variables (and the enclosure ones), but if you really want, you can import ctypes and do the hack.
    thautwarm
        10
    thautwarm  
       2018-01-07 13:22:27 +08:00   ❤️ 1
    为什么会 NameError,这是符号表加载的问题。

    locals()设置新 name 是无意义的,虽然每一次在一个作用域拿出的 locals()都是同一个引用,但是导入符号并非直接使用 locals(),也就是说你对它的修改,如果是修改 mutable 对象的内部还好,直接改 immutable 自然是无效的。

    Python 确定从哪里加载符号,代码编译到字节码时就确定了。既然编译时找不到 lis3 的定义,自然就认为它来自 globals()里面。而你在代码解释时才修改 locals(),那么犯错的原因,如下有俩

    1. locals()不是 func 作用域加载符号所用的符号表
    2. lis3 被预先认为是定义在 globals()里的。



    P.S 关于 locals()的行为。
    locals()其中一部分类似于一个作用域符号管理结构 S 上的 view。另一部分,locals()应该也有一个"固有成分",当你对 locals()进行__setitem__操作,并不是没有起效果,而是因为 locals 的__getitem__是有限搜索 S 的 item,没有的话再搜索 locals()的"固有成分"。

    def g(x=20):
    d = locals()
    locals()['x'] = 10
    print(locals()['x'])
    print(d is locals())
    g()
    # => 20
    # True

    def g():
    locals()['x'] = 10
    print(locals()['x'])
    g()
    # 10

    以上。。
    linlin12914
        11
    linlin12914  
       2018-01-08 11:37:07 +08:00
    @xpresslink 菊。。。菊部?
    xpresslink
        12
    xpresslink  
       2018-01-08 12:01:43 +08:00
    @linlin12914 最鄙视就是你这种人,就知道盯着菊部看:-)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1186 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:16 · PVG 02:16 · LAX 10:16 · JFK 13:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.