【问题标题】:defining variable from string从字符串定义变量
【发布时间】:2023-03-09 19:49:01
【问题描述】:

我正在尝试在函数内部定义变量。 vars() 显示变量已创建,但给了我 NameError: 异常。我做错了什么?

def a(str1):
    vars() [str1] =  1
    print vars()
    print b


a('b')

输出:

{'str1': 'b', 'b': 1}

例外:

NameError: global name 'b' is not defined

【问题讨论】:

标签: python scope


【解决方案1】:

您正在调用未定义的行为。来自documentation of vars()

注意不应修改返回的字典:对相应符号表的影响未定义。

其他答案给出了可能的解决方案。

【讨论】:

    【解决方案2】:

    您的代码对我有用。也许您应该尝试另一种方法:

    exec(str1 + '=1')
    

    这将执行b=1

    【讨论】:

    • exec() 在函数范围内将在该函数本地范围内工作。
    【解决方案3】:

    如果您不明白为什么构造不起作用,那么下一个必须阅读您的代码的人也不会。如果你的意思是

    b = 1   
    

    你应该这么说。在这种情况下,vars() 使您可以访问函数本地字典,因此您的代码相当于

    def a():
       b = 1
    

    其中ba 的本地对象,并在从a 退出时超出范围时消失。

    过早的优化是许多人试图猜测 Python 的根源

    from itertools import izip
    import timeit
    
    import msw.wordlist
    
    def zip_list(p):
        """construct a dictionary of length 100 from a list of strings"""
        return dict(zip(p[:100], p[100:]))
    
    def izip_list(p):
        """as zip_list but avoids creating a new list to feed to dict()"""
        return dict(izip(p[:100], p[100:]))
    
    def pass_list(p):
        """take 100 elements of a list and do nothing"""
        for i in p[:100]:
            pass
    
    def exec_pass_list(p):
        """exec() a no-op 100 times"""
        for i in xrange(100):
            exec('pass')
    
    
    # returns a list of 64'000 unique lowercase dictionary words for tests
    words = msw.wordlist.Wordlist()
    words.shuffle()
    words = words[:200]
    print 'words', words[:5], '...'
    
    for func in ['zip_list', 'izip_list', 'pass_list', 'exec_pass_list']:
        t = timeit.Timer('%s(words)' % func,
                'from __main__ import words, %s' % func)
        print func, t.repeat(number=10**5)
    

    产生:

    words ['concatenated', 'predicament', 'shtick', 'imagine', 'stationing'] ...
    zip_list [1.8603439331054688, 1.8597819805145264, 1.8571949005126953]
    izip_list [1.5500969886779785, 1.5501470565795898, 1.5536530017852783]
    pass_list [0.26778006553649902, 0.26837801933288574, 0.26767921447753906]
    exec_pass_list [74.459679126739502, 75.221366882324219, 77.538936853408813]
    

    我没有费心去尝试实现 OP 试图做的任何事情,因为不构建字典排序的速度要慢 50 倍,这使得进一步的测试有点愚蠢。

    【讨论】:

    • 我认为关键是他希望变量名是动态的。
    • 而且我明确没有回答问题的隐含方面,因为向甚至无法表达问题的人提供的分发解决方案可能不会得到很好的使用。是的,这是一种教学立场,但 SO 是关于教学的。
    • 好的,这应该是尽可能快的,所以不是制作 100 个预定义键的字典:值我只是从字符串生成 var。这就是为什么。
    • @damir:然后测量一下,你会发现exec 方法可能是所有可能的替代方案中最慢的。
    • @damir:我很确定你不会“尽可能快”。
    猜你喜欢
    • 1970-01-01
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 1970-01-01
    • 2018-12-01
    • 1970-01-01
    • 2020-11-14
    相关资源
    最近更新 更多