如何通过while循环动态创建变量?

Noa*_*h R 142 python variables

我想通过Python中的while循环动态创建变量.有没有人有这样做的创造性手段?

Jos*_*del 128

除非需要创建一堆变量名称,否则我只会使用一个字典,您可以在其中动态创建密钥名称并将值与每个名称相关联.

a = {}
k = 0
while k < 10:
    <dynamically create key> 
    key = ...
    <calculate value> 
    value = ...
    a[key] = value 
    k += 1
Run Code Online (Sandbox Code Playgroud)

新的"集合"模块中还有一些有趣的数据结构可能适用:

http://docs.python.org/dev/library/collections.html

  • @Josh和其他人......在字典"a"中创建一个项目(键,值)与在"locals()"或"globals()"中创建相同的项目也没有什么不同.我想知道为什么我被一些downvote狙击手贬低为我的答案在`globals()中创建一个项目,而Gintautas Miliauskas的答案被赞成,这个答案没有给出`<动态创建键>的方法`被投票3次. (8认同)
  • @eyquem局部变量未实现为字典.几乎总是,`locals()`函数从局部变量创建一个字典,但除非你调用`locals()`,否则字典不存在. (3认同)
  • @eyquem,本地命名空间被实现为堆栈中的插槽,因此字节码可以直接引用它们作为堆栈帧中的偏移量(加上自由变量,当你调用`locals()时也包括它们.例外在Python 2中. x当你在一个函数中使用`exec`而没有为exec指定一个本地命名空间时.我不确定在哪里记录它:它不是语言定义的一部分,因为不同的实现可以选择不同的方式来实现本地命名空间. (3认同)
  • @eyquem我没有给出任何特定的方法来创建密钥,因为我对OP在实践中需要的命名方案一无所知.相反,我只是给出了最通用和最简洁的方案来解决问题. (2认同)
  • 这是最好的答案。因此,这应该是规范的问题。 (2认同)

eyq*_*uem 55

使用globals()可以实现:

import random

alphabet = tuple('abcdefghijklmnopqrstuvwxyz')


print '\n'.join(repr(u) for u in globals() if not u.startswith('__'))

for i in xrange(8):
    globals()[''.join(random.sample(alphabet,random.randint(3,26)))] = random.choice(alphabet)

print

print '\n'.join(repr((u,globals()[u])) for u in globals() if not u.startswith('__'))
Run Code Online (Sandbox Code Playgroud)

一个结果:

'alphabet'
'random'

('hadmgoixzkcptsbwjfyrelvnqu', 'h')
('nzklv', 'o')
('alphabet', ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'))
('random', <module 'random' from 'G:\Python27\lib\random.pyc'>)
('ckpnwqguzyslmjveotxfbadh', 'f')
('i', 7)
('xwbujzkicyd', 'j')
('isjckyngxvaofdbeqwutl', 'n')
('wmt', 'g')
('aesyhvmw', 'q')
('azfjndwhkqgmtyeb', 'o')
Run Code Online (Sandbox Code Playgroud)

我使用随机因为你没有解释要给出的"变量"的名称,以及要创建的值.因为我不认为可以在不将其绑定到对象的情况下创建名称.

  • @Ned Batchelder也许这个问题是错误的.但我认为他可能会更好地得到两个答案:1-是的,你可以做你想做的事情2-但是你想进入的方式对于这个理由并不是一个很好的方式.这样做,OP会学到两件事:Python功能强大,以及一些正确编码的建议.相反,如果任何人被阻止自己思考并思考一个问题,那就是对脑力激荡和反思的束缚 (37认同)
  • 这是一个很好的答案.我偶然发现了这个答案的合理需要,使我无法编写一个几乎重复的问题. (22认同)
  • 我认为你被投票的原因是因为垃圾密钥输入全局字典通常不被认为是最佳做法.实际上在你自己的代码示例中,如果你的随机密钥生成器生成一个已经在globals dict中的密钥(例如密钥"alphabet"),你会想到会发生什么.此外,我认为OPs问题暗示他需要在创建后获得他的"变量".他如何使用您的解决方案将其动态变量与已存在于全局范围内的变量区分开来?在这种情况下,单独的dict更好. (10认同)
  • 值得指出的是,这个答案提供了动态创建*global*变量的方法.这意味着在`globals()`上定义的每个变量都将在模块名称空间中继续存在,直到程序结束.大多数情况下,当一个人说"变量"时,它们意味着一个*function local*变量,它只存在于函数执行的上下文中.在这种情况下,`globals()`可能不是问题的解决方案.考虑明确使用字典,如JoshAdel提供的答案. (4认同)
  • OP 需要一种方法来创建与许多名称相关联的许多值。他将其表述为“动态创建变量”,但使用字典是解决他真正问题的正确方法。 (3认同)
  • @free-dom 谢谢。你的话有3个不同的点。1) _not well thinking_ 不是一个解释性的论点,甚至不是一个权威性的论点,它是一种“最常见”风格的论点。对我来说这还不够 2) 是的,我的代码中存在潜在问题,但我的目标不是预测快速编写代码的所有后果,只是向诺亚展示他的要求是可能的为了。SO 的兴趣在于,如果一个解决方案不是很好,它会在辩论中被其他一些解决方案强调。如果 OP 需要补充更正,他们会得到 (2认同)
  • 虽然可能不是最好的解决方案,但这是一个有效的答案。+1。我实际上用它来回答这个问题 [here](http://stackoverflow.com/questions/11748780/is-it-possible-something-like-lvalue-of-perl-or-setf-of-lisp-in-蟒蛇/11750015#11750015)。不仅如此,同样的概念也可以应用于使用 locals()。你没问题,eyquem 的例子永远不应该被逐字使用,但是 eyquem 不需要为 OP 编写项目。在尝试使用此方法之前,OP 应确保`somevar not in globals()`。 (2认同)

小智 45

使用exec()方法.例如,假设您有一个字典,并且您希望将每个键转换为具有原始字典值的变量,则可以执行以下操作.

Python 2

>>> c = {"one": 1, "two": 2}
>>> for k,v in c.iteritems():
...    exec("%s=%s" % (k,v))

>>> one
1
>>> two
2
Run Code Online (Sandbox Code Playgroud)

Python 3

>>> c = {"one": 1, "two": 2}
>>> for k,v in c.items():
...    exec("%s=%s" % (k,v))

>>> one
1
>>> two
2
Run Code Online (Sandbox Code Playgroud)

  • @ chris-piekarski感谢您的回答.想要做这样的事情的一个原因是当你需要与希望输入作为局部变量传递的第三方软件进行通信时,并且在编译时你不知道它期望的变量(我正在创建一个Paraview插件例如,它强加了这种约束). (4认同)
  • 请注意,这在函数执行上下文中的Python 3中不起作用。在顶层(模块)上下文中仍然可以。如果您需要创建模块变量,建议您编辑`globals()`dict,或在模块对象上调用`setattr()`。 (3认同)
  • 我还要强调的是,一般来说,当键或值由外部数据(用户输入、文件或任何内容)提供时,这会带来安全风险。使用 eval/exec 时的常见警告适用。您不希望有人将值设置为“send_me_all_your_private_data()”并在您的计算机上执行它。 (2认同)
  • 实际上,这是一个很好的答案,并且是特定情况下的唯一解决方案。假设您有一个代表库存的数组。假设此库存可以在其中放入容器,并且这些容器都有自己的库存,代表该容器正在存放的物品。我知道这是唯一能够将INDEXES存储在字符串中并能够对其进行更改并动态访问不同索引的唯一方法,例如,如果您更改了要查找的容器。 (2认同)

Joh*_*hin 28

将东西填充到全局和/或本地命名空间中并不是一个好主意.使用dict是如此的一些其他语言... d['constant-key'] = value只是看起来很尴尬.Python是OO.用大师的话来说:"""命名空间是一个很棒的主意 - 让我们做更多的事情!"""

像这样:

>>> class Record(object):
...     pass
...
>>> r = Record()
>>> r.foo = 'oof'
>>> setattr(r, 'bar', 'rab')
>>> r.foo
'oof'
>>> r.bar
'rab'
>>> names = 'id description price'.split()
>>> values = [666, 'duct tape', 3.45]
>>> s = Record()
>>> for name, value in zip(names, values):
...     setattr(s, name, value)
...
>>> s.__dict__ # If you are suffering from dict withdrawal symptoms
{'price': 3.45, 'id': 666, 'description': 'duct tape'}
>>>
Run Code Online (Sandbox Code Playgroud)

  • _"名称空间是从名称到对象的映射.**大多数名称空间当前都是作为Python字典**实现的,但这通常不会以任何方式显着(性能除外),并且可能在将来发生变化.名称空间的示例是:内置名称的集合(诸如abs()和内置异常名称之类的函数);模块中的全局名称;以及函数调用中的本地名称.**在某种意义上,属性集合一个对象也形成一个命名空间.**"_ (3认同)
  • 我不明白你想说什么.为什么全局和本地命名空间不是好主意?因为_"大多数命名空间目前都是作为Python词典实现的"_?那些字典是_"其他语言是什么"_?为什么这个批评字典?您认为实例的命名空间比字典更好用吗?嗯......你知道吗: (2认同)

Pjl*_*Pjl 6

vars()['meta_anio_2012'] = 'translate'
Run Code Online (Sandbox Code Playgroud)

  • 这与执行 `locals()['meta_anio_2012'] = 'translate'` 相同,这在函数中不起作用,并且在文档中特别警告。它还受到其他答案的评论中指出的许多问题的困扰。 (8认同)
  • 使用 [vars()](https://docs.python.org/3/library/functions.html#vars) 函数来修改对象的变量绝对没有错,但您需要将其稍微更新为使用它来将变量设置为模块(通过传入模块对象)。`vars(sys.modules[__name__])['my_variable'] = 'value'` 这样做没有错,因为它获取底层对象的 `__dict__`。这可能不起作用的唯一时间是正在获取的对象是否具有对属性的写入权限。 (2认同)

Joe*_*ine 6

关键字参数允许您将变量从一个函数传递到另一个函数。通过这种方式,您可以使用字典的键作为变量名(可以在while循环中填充)。字典名称只需要在**调用时放在前面。

# create a dictionary
>>> kwargs = {}
# add a key of name and assign it a value, later we'll use this key as a variable
>>> kwargs['name'] = 'python'

# an example function to use the variable
>>> def print_name(name):
...   print name

# call the example function
>>> print_name(**kwargs)
python
Run Code Online (Sandbox Code Playgroud)

没有**,kwargs只是一个字典:

>>> print_name(kwargs)
{'name': 'python'}
Run Code Online (Sandbox Code Playgroud)