【问题标题】:Set the name of a python object/variable with a string使用字符串设置 python 对象/变量的名称
【发布时间】:2013-02-08 01:04:00
【问题描述】:

大多数人可能会说这是个坏主意。我想使用字符串的内容作为变量的名称。我想完成可怕的事情:

s = 'x'
x = 1

变量名称x 来自字符串s(不知何故?)。

要回答“为什么?”,假设我有一个 x 的全局默认值,我想要在函数中覆盖该选项。但是:

x = 0
def f(**kw):
    print x
f(x=1)

打印0 而不是1。如果我可以使用 kw.keys() 中的字符串重新分配 x(或任何其他全局设置的变量),那么我会很高兴。

我意识到这适用于在f 中重新分配x

x = 0
def f(x=x):
    print x
f(x=1)

但是我想在我的命名空间中有很多变量的情况下这样做,我可能在某些时候想要覆盖而不重写模块中的每个函数定义。

【问题讨论】:

  • 为什么不保留这些“全局”状态变量的字典?

标签: python string function keyword argument-passing


【解决方案1】:

查看exec

>>> print x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> s = 'x'
>>> exec(s + " = 1")
>>> print x
1 

另见:How can I assign the value of a variable using eval in python?

经过一些实验,这似乎也有效:

>>> print x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> s = 'x'
>>> globals()[s] = 1
>>> print x
1

【讨论】:

  • 几乎没有理由使用 eval 或 exec。在这种情况下,您可以改用 getattr 或 setattr。
  • 对于我自己的学习,在这种情况下你会如何使用 setattr?
  • 您编辑的答案是直接设置全局变量的一种方法。但我通常为真正全局的常量(只读)值保留全局变量。如果您需要保持状态,请使用类和实例变量。
  • @JesseVogt 感谢您对原始问题的直接回答。我很欣赏其他帖子说 exec 是一件不好的事情,但很高兴知道它在绑定中。
【解决方案2】:

您应该重新考虑使用 global 关键字 (http://docs.python.org/2.7/reference/simple_stmts.html#the-global-statement)

我建议也看看Use of "global" keyword in Python

此外,正如 promanow 所建议的,使用全局可变对象可能是更好的方法。

但是,请记住,从维护的角度来看,拥有大量可能修改或依赖于变异全局的代码是非常可怕的想法。小心行事。

【讨论】:

    【解决方案3】:

    通过函数参数赋值并不明显,因此不被视为 Pythonic(Python 不是 C)。见import this

    我完成平面配置的廉价方式是通过全局部分字典:

    In [1]: from functools import partial
    In [2]: config = partial(dict)
    In [3]: def f(x=None):
       ...:     print x or config.x
       ...:     
    In [4]: config.x = 'foo'
    In [5]: f()
    foo
    

    具有这种效果的东西是显而易见的、可读的,因此更易于维护。

    【讨论】:

      【解决方案4】:

      但是我想在我的命名空间中有很多变量的情况下这样做,我可能在某些时候想要覆盖而不重写模块中的每个函数定义。

      听起来你想要上课:

      class Foo(object):
          x = 0
          def f(self):
              print self.x
      
      my_foo = Foo()
      my_foo.x = 1
      my_foo.f()
      

      【讨论】:

      • 我相信你是对的,这是最好的全局答案。我知道我需要学习如何在我的代码中使用类。因此,考虑到我在一个具有许多不同交互功能的模块中执行所有这些操作,那么我想我应该将所有这些相关功能包装在一个类中,以便更好地控制它们共享的参数。我想这将避免或至少有助于解决所有这些函数必须来回传递参数的问题。
      【解决方案5】:

      我使用以下内容从一个全局数据库中为感兴趣的目标创建动态自定义建模数据库:

      DBs = ["Target_1_DB","Target_2_DB","Target_3_DB"]
      
      for db in DBs:
          print(db)    
          exec_str = "Modeling_DB_Base = " + db
          exec(exec_str)
          #s = "Modeling_DB_Base"
          #globals()[s] = db
          print(Modeling_DB_Base.shape)
      

      使用注释掉的 globals() 会导致错误消息:AttributeError: 'str' object has no attribute 'shape'

      【讨论】:

        【解决方案6】:

        您可以使用以下解决方案:

        s = 'x'
        locals()[s] = 1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-12-03
          • 1970-01-01
          • 2014-06-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多