TL;DR
我在 Windmill 的代码中添加了一些功能 - 保存的动词分数计数器有助于优先考虑低分词缀,一些跳过或退出的选项,我将 dict 作为 json 保存在一个文件中,我还添加了一些建议网页抓取动词。
学习工具
- 目标:通过测试用户经常失败的动词来简化动词的学习。
用例
请注意,我在搜索相同的一般用例时遇到了这篇文章。
即“我想学习X语言的动词,并通过一个小程序进行改进。”
具体来说,我在学习葡萄牙语时还需要一个动词变位学习工具。葡萄牙语在某些方面与西班牙语相似,其中之一就是动词变位。
我还考虑了您想要一个动词变位学习工具这一事实,我认为这是问题通常所暗示的 - 该工具的使用不仅限于西班牙语。从问题中我了解到学习工具应该可以帮助您学习-例如与在你学习的过程中适应你,并优先考虑你一直犯错的单词,它应该很容易理解它是如何工作的。
针对弱点的设计
基本上,我们希望跟踪我们的分数以针对我们的弱点,否则程序将回到我们已经熟悉的动词*。我认为这在这样的学习工具中很重要,否则使用起来会浪费时间。
* 添加有关动词是规则还是不规则的信息可能是一个想法。这样我们就可以在某种时态的规则形式被很好地理解之后,优先考虑不规则动词。这里的“好”可以由工具的用户启发式地或经验地决定,作为一个研究问题。两者都取决于用户的需求和工具存储的信息。
获取数据
首先我们需要动词表数据。
您可以选择手动输入数据,这需要大量的乏味和耐心,或者自动输入,如果您不了解网络抓取,则需要学习的意愿。我建议您在 python 中查找 webscraping,这样您就可以学习使用 requests 和 lxml 或 beautifulsoup 等库构建获取动词所需的基本命令。取决于您决定抓取哪个网站,因为有许多在线词典可用于抓取有关动词变形的信息。
数据格式选择
保存抓取的数据时,您有一些选择。
json
如果您想使用字典,我建议将其保存为 json 文件并使用 python json 库加载。这样您就可以将文件与代码分开。
所以你的动词在一个名为spanish_verbs.json的文件中看起来像这样:
{
"hacer": {
"present": {
"yo": "hago",
"tu": "haces",
"elellausted": "hace",
"nosotros": "hacemos",
"ellosellasuds": "hacen"
},
"preterite": {
"yo": "hice",
"tu": "hiciste",
"elellausted": "hizo",
"nosotros": "hicimos",
"ellosellasuds": "hicieron"
}
},
"tener": {
"present": {
"yo": "tengo",
"tu": "tienes",
"elellaud": "tiene",
"nosotros": "tenemos",
"ellosellasuds": "tienen"
},
"preterite": {
"yo": "tuve",
"tu": "tuviste",
"elellausted": "tuvo",
"nosotros": "tuvimos",
"ellosellasuds": "tuvieron"
}
}
}
所以现在你可以用一些简单的东西来加载它们,而不是在程序中包含动词:
with open("spanish_verbs.json", 'r') as f:
verbs = json.load(f)
CSV
否则我会将数据保存为 csv 或 tsv 并使用 pandas 之类的东西来加载文件。
程序动作和界面
当前界面是基于终端的。如果你想更进一步,你可以使用 tkinter 或 wxpython 之类的东西来构建 GUI。
启动程序
从终端启动程序:
python3 ./ask_verb_tense_example.py spanish_verbs.json verb_scores.tsv
动作
您可以使用的操作是
- 键入动词并按回车键检查是否正确
或
- 选择一个选项并按回车键
关于选项,您可以选择
记录分数
程序中还有一个动词评分数据框,在您完成所有动词一次后,它会更新并跟踪和训练您使用一组评分最差的动词中的一个随机动词。
计分规则
评分规则如下:
代码
代码如下:
import random
import readline
import sys
import os
import json
import pandas as pd
with open(sys.argv[1], 'r') as f:
verbs = json.load(f)
def load_verb_scores(filename):
if not os.path.exists(filename):
verb_scores = pd.DataFrame(
{
"verb": pd.Series([], dtype='str'),
"correct": pd.Series([], dtype='int'),
"incorrect": pd.Series([], dtype='int'),
"total": pd.Series([], dtype='int'),
},
)
else:
verb_scores = pd.read_csv(filename, sep='\t')
return verb_scores
def update_scores(verb_scores, verb, correct=False, incorrect=False):
total=0
if correct and incorrect:
raise Exception("Answer to question cannot be both correct and incorrect!")
if (verb_scores.verb==verb).any():
if correct:
verb_scores.loc[(verb_scores.verb==verb),"correct"]+=1
elif incorrect:
verb_scores.loc[(verb_scores.verb==verb),"incorrect"]+=1
verb_scores.loc[(verb_scores.verb==verb),"total"]+=1
else:
verb_scores=verb_scores.append(
{
"verb":verb,
"correct":int(correct),
"incorrect":int(incorrect),
"total":1,
},
ignore_index=True
)
return verb_scores
verb_scores = load_verb_scores(sys.argv[2])
total_to_practice = sum([len(y) for v in verbs.values() for y in v.values()])
print(f"found {total_to_practice} verbs to practice")
while True:
if verb_scores.shape[0]==total_to_practice:
# random choice out of poorest performing verbs
poorest_performance = (verb_scores.incorrect/verb_scores.total).nlargest(5).index
verb = random.choice(verb_scores.loc[poorest_performance].verb.tolist())
v_index=verb_scores.verb==verb
# warning: some verbs may correspond to multiple infinitives/tenses/articles !
infinitive = [i for i, v in verbs.items() for y in v.values() if verb in y.values()][0]
tense = [t for v in verbs.values() for t, y in v.items() if verb in y.values()][0]
article = [a for a,v in verbs.get(infinitive).get(tense).items() if verb==v][0]
incorrect_pct = (verb_scores[v_index].incorrect*100/verb_scores[v_index].total).item()
print("selected verb: ", infinitive, " wrong ", incorrect_pct, "% of the time")
else:
# random choice over all verbs to begin with
infinitive = random.choice(list(verbs.keys()))
tense2articles2verbs = verbs.get(infinitive)
tense = random.choice(list(tense2articles2verbs.keys())) # choose a tense
articles2verbs = tense2articles2verbs.get(tense)
article = random.choice(list(articles2verbs.keys())) # choose an article
verb = articles2verbs.get(article)
question = "What is the {} {} form of {}?\n> ".format(
tense,
article,
infinitive,
)
while True:
response = input("{}".format(question))
if verb == response.lower().strip():
print("\033[92mCorrect!\033[0m")
verb_scores = update_scores(
verb_scores,
verb,
correct=True
)
break
elif 'p' == response.lower():
print("\033[91mPassing... the correct verb was {}\033[0m".format(verb))
verb_scores = update_scores(
verb_scores,
verb,
incorrect=True
)
break
elif 'q' == response.lower():
print("Safe quit.")
verb_scores.to_csv(sys.argv[2], sep='\t', index=False)
sys.exit(0)
else:
verb_scores = update_scores(
verb_scores,
verb,
incorrect=True
)
print("\033[91mIncorrect, try again.\033[0m")
示例输出
程序输出如下所示:
What is the present nosotros form of hacer?
> hacemos
Correct!
在你遍历所有可能的动词后,它会开始遍历你最容易出错的前 5 个动词。
$ python3 ./ask_verb_tense_example.py spanish_verbs.json verb_scores.tsv
found 20 verbs to practice
selected verb: tener wrong 100.0 % of the time
What is the preterite tu form of tener?
> tenes
Incorrect, try again.
...
分数文件
您还可以访问名为verb_scores.tsv 的动词分数文件,该文件在用户按q 保存并退出后由程序创建和更新。通过这种方式,您可以通过将 tsv 导入某些电子表格软件来跟踪您的进度。
verb correct incorrect total
hacemos 0 3 3
tiene 1 1 2