我刚刚完成了一门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。如果你看到我应该改进的其他事情,请不要犹豫,提及。
答案 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代码而不是他们的名字,那么它将被执行,因此会造成很大的损失!!!
我提到做你想做的事情是设计缺陷的常见迹象。原因很简单,您的代码不会暴露在外部,也不应该依赖于实际数据。应用于您的示例:为什么字典的名称(仅作为程序内部的对象)取决于“外部世界”中的任何内容?
所以,这里有一些关于如何继续的提示:
WordsCollection
属性的类name
,并使用您想要的任何变量名创建该类的实例。