【问题标题】:Add new dictionary with the name given by raw input (Python 2.7)使用原始输入给出的名称添加新字典(Python 2.7)
【发布时间】:2018-02-01 01:07:00
【问题描述】:

我刚刚完成了 Python 课程,并且正在着手我的第一个项目,这是一个用于练习西班牙语动词及其变位的工具。该工具正在运行,但现在我想改进它。例如,目前处理数据比较困难(例如将过去时添加到动词 + 复杂的随机测验功能)。

然而,我偶然发现了几个问题,其中之一是: 如何添加新字典并根据原始输入为该字典命名?我认为这应该不难,但经过大量搜索后仍未找到解决方案。

我有两个文件:一个包含代码和一个 .txt 文件,其中包含作为字典的所有动词的单独行。下面你会看到我添加新动词并将其附加到 .txt 文件的函数。

我的 .txt 文件中的一行示例:

to talk = {'present': ['hablo', 'hablas', ... ]}

当前代码:

def add_verb():
    verb = {}
    name = (raw_input("Verb in Dutch: "))
    tense = (raw_input("Verb tense: ")) 

    conjugations = []
    conjugations.append(raw_input("Yo: "))
    conjugations.append(raw_input("Tú: "))

    verb_dict[tense] = conjugations

    with open("verbs.txt", "a") as abc:
        abc.write("%s = {'%s': %s}\n" % (name, tense, conjugations))

基本上,我想要的是这样的:

abc.write(dictionary)

因此,我希望将字典按原样写入文件,但使用原始输入给出的字典名称。

我目前也在考虑使用 Verb 类,因为我认为这会使该工具变得更好,但后来我偶然发现了完全相同的问题(如何为新类实例指定由 raw 给出的名称输入?)。

附:如果您看到其他我应该改进的地方,请随时提及。

【问题讨论】:

  • 不要将变量命名为dictlisttype,它们会隐藏python 的内置类型和方法。听起来您只需要一个嵌套字典。
  • 是的,我更改了这篇文章的名称(在我的原始代码中,它们是荷兰语)
  • 即使它们是荷兰语,“列表”也不是很有指示性,最好将其命名为与其实际表示的内容相对应的名称,这将使您的代码很多更清晰。除非我误解了,并且在您的英文翻译中,您还更改了名称的语义。另外,海海:)
  • 嗨@IzaakvanDongen!谢谢,我担心它会使它复杂化而不是让它变得更容易,但我明白为什么它没有。我编辑了帖子!

标签: python python-2.7 dictionary


【解决方案1】:

从您问题中的其他上下文来看,听起来您实际上可能会受益于与此更相似的嵌套字典结构:

import pprint

spanish_dictionary = {"hablar": {"present": ["hablo", "hablas", "hablamos", ...],
                                 "past": ["i'm", "out", "of", "my", "depth"]},
                      "comer": {"present": ["como", ...] #you get the idea
                                }
                     }

def add_verb():
    spanish_dictionary["tener"] = {"present": ["tengo", ...]}

add_verb()

pprint.pprint(spanish_dictionary)

请注意,如果您将省略号替换为适当的内容,它将在 Python2 中运行,并且它实际上已经在 Python3 中运行,并给出了输出:

{'comer': {'present': ['como', Ellipsis]},
 'hablar': {'past': ["i'm", 'out', 'of', 'my', 'depth'],
            'present': ['hablo', 'hablas', 'hablamos', Ellipsis]},
 'tener': {'present': ['tengo', Ellipsis]}}

请原谅我非常有限的西班牙语,希望这足以证明结构。正如您所看到的,通常最好不要使用要更改名称的字典,而是将它们放在更大的字典中,因此不必对exec 做任何困难和危险的事情,您可以添加通过向更大的字典添加值来创建字典。如果你有一个由raw_input 起的名字,比如说:

new_verb_name = raw_input()
new_verb_data = some_processing(raw_input())
spanish_dictionary[new_verb_name] = new_verb_data

关于你有一个动词类的想法 - 我认为这可能是一个非常好的想法,但我有一个提示。动词可能是不可变的,因为动词的变位不会改变,所以collections.namedtuple 似乎适合这项任务。 namedtuple 允许您基本上定义一个类而无需定义它,如果它需要做的只是存储值。注意namedtuple实际上是一个返回类的工厂函数。你可以这样使用它:

from collections import namedtuple

Verb = namedtuple("Verb", "past present")
Conjugation = namedtuple("Conjugation", "yo tu")

spanish_dict = {"hablar": Verb(present=Conjugation(yo="hablo", tu="hablas"),
                               past=Conjugation(yo="yo hablo in past :p", tu=...))
               }

print(spanish_dict)
print(spanish_dict["hablar"].present.tu)

这有输出:

{'hablar': Verb(past=Conjugation(yo='yo hablo in past :p', tu=Ellipsis), present=Conjugation(yo='hablo', tu='hablas'))}
hablas

如您所见,能够使用.present.tu 访问动词的属性非常具有表现力。不过,这只是一个例子——你会做所有西班牙人的实际工作:)

看看这条线会很有趣

Verb = namedtuple("Verb", "past present")

相当于在一个完整的类定义中。运行即可查看

Verb = namedtuple("Verb", "past present", verbose=True)

请注意,这会导致 50 多行代码。老实说,实现namedtuple 的人可能只是在炫耀一点;)。但这确实说明了namedtuple 工厂的强大。

【讨论】:

  • 我花了一点时间来实现(因为我还是编码新手),但是嵌套字典使整个工具/代码变得更好、更容易!接下来我将尝试使用这些类,必须阅读更多内容,但这似乎更好(特别是对于工具中的“随机测验”功能)。 Dankjewel/muchas gracias! ;)如果您想学习西班牙语,请在完成后随意使用该工具,哈哈!
【解决方案2】:

确实不建议您这样做,因为它混合了数据(您的用户输入)和代码,这通常是一些设计缺陷的迹象。

但是,为了记录,你可以使用exec实现你想要的:

>>> name = input("What is your name?\n")
What is your name?
test

>>> exec(f"{name} = dict()")  # Python 3.6 and above
>>> exec("{0} = dict()".format(name))  # Python 2.7 & 3.5
>>> print(test)
{}

警告

exec 只是执行它作为参数获得的代码。正如 cmets 中的@Błażej Michalik 所提醒的那样,这非常危险,尤其是结合用户的输入。

在我的例子中,如果用户决定输入实际的 Python 代码而不是他们的名字,它将被执行,因此可能会造成巨大的损失!!!


为什么混合数据和代码会如此糟糕,以及从哪里开始?

我提到过,做你想做的事是设计缺陷的常见标志。原因很简单,你的代码没有暴露在外部,不应该依赖于实际数据。应用于您的示例:为什么字典的名称(仅存在于程序内部的对象)取决于“外部世界”的任何内容?

所以,这里有一些关于如何进行的提示:

  • 以 JSON 格式(或 YAML、TOML、XML 等)存储您的所有数据。考虑到您将数据存储在文本文件中的方式,您已经离那不远了。它只会让它更标准。
  • 如果您使用用户输入,则将该输入存储在一个变量中,该变量具有您想要的任何名称。例如,假设您希望用户创建一些单词集合,只需创建一个类 WordsCollection,该类将具有 name 属性,然后使用您想要的任何变量名称创建该类的实例。
  • 如果您开始学习 Python,我宁愿选择使用 Python 3 :)

【讨论】:

  • 不推荐,因为exec() 是向您的应用程序引入代码注入漏洞的可靠方法。
  • 嗯,这就是为什么我提到不被推荐的原因:) 我会在我的答案中添加更多警告!
  • 你确定这是他们想要做的吗?在我看来,他们想要的只是将其写入文件,而不是将其引入全局命名空间。另外,考虑到这是在“Python 2.7”中,我不会使用 f-string。
  • @IzaakvanDongen 你对 Python 2.7 是正确的,我将编辑我的答案。关于 OP 想要做什么,我也不确定他们试图实现什么,但如果他们得到一个以用户输入命名的字典,很容易使用 str() 将其转储到文件中。
  • @filaton 感谢您的回复!我明白为什么不推荐它了,然后我会寻找解决方法,首先查看您对如何进行的建议!谢谢
猜你喜欢
  • 2018-11-03
  • 1970-01-01
  • 2023-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多