使用raw input(Python 2.7)给出的名称添加新字典

时间:2017-08-23 12:29:26

标签: python python-2.7 dictionary

我刚刚完成了一门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给出的名称输入?)。

P.S。如果你看到我应该改进的其他事情,请不要犹豫,提及。

2 个答案:

答案 0 :(得分:2)

从您问题的其他上下文来看,听起来您可能真正受益于更类似于此的嵌套字典结构:

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工厂的强大功能。

答案 1 :(得分:0)

我们不建议你做什么,因为它混合了数据(你的用户输入)和代码,这通常是一些设计缺陷的标志。

但是,为了记录,您可以使用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只是执行它作为参数获取的代码。正如@BłażejMichalik在评论中提醒的那样,这非常危险,特别是与用户的输入相结合。

以我的例子为例,如果用户决定输入实际的Python代码而不是他们的名字,那么它将被执行,因此会造成很大的损失!!!


为什么混合数据和代码以及从何处开始这么糟糕?

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

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

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