跳转到主要内容

正确生成复数、单数名词、序数词、不定冠词

项目描述

https://img.shields.io/pypi/v/inflect.svg https://img.shields.io/pypi/pyversions/inflect.svg tests Ruff https://readthedocs.org/projects/inflect/badge/?version=latest https://img.shields.io/badge/skeleton-2024-informational https://tidelift.com/badges/package/pypi/inflect

名称

inflect.py - 准确生成复数、单数名词、序数词、不定冠词和基于单词的数字表示。此功能仅限于英语。

摘要

import inflect

p = inflect.engine()

# METHODS:

# plural plural_noun plural_verb plural_adj singular_noun no num
# compare compare_nouns compare_nouns compare_adjs
# a an
# present_participle
# ordinal number_to_words
# join
# inflect classical gender
# defnoun defverb defadj defa defan


# UNCONDITIONALLY FORM THE PLURAL

print("The plural of ", word, " is ", p.plural(word))


# CONDITIONALLY FORM THE PLURAL

print("I saw", cat_count, p.plural("cat", cat_count))


# FORM PLURALS FOR SPECIFIC PARTS OF SPEECH

print(
    p.plural_noun("I", N1),
    p.plural_verb("saw", N1),
    p.plural_adj("my", N2),
    p.plural_noun("saw", N2),
)


# FORM THE SINGULAR OF PLURAL NOUNS

print("The singular of ", word, " is ", p.singular_noun(word))

# SELECT THE GENDER OF SINGULAR PRONOUNS

print(p.singular_noun("they"))  # 'it'
p.gender("feminine")
print(p.singular_noun("they"))  # 'she'


# DEAL WITH "0/1/N" -> "no/1/N" TRANSLATION:

print("There ", p.plural_verb("was", errors), p.no(" error", errors))


# USE DEFAULT COUNTS:

print(
    p.num(N1, ""),
    p.plural("I"),
    p.plural_verb(" saw"),
    p.num(N2),
    p.plural_noun(" saw"),
)
print("There ", p.num(errors, ""), p.plural_verb("was"), p.no(" error"))


# COMPARE TWO WORDS "NUMBER-INSENSITIVELY":

if p.compare(word1, word2):
    print("same")
if p.compare_nouns(word1, word2):
    print("same noun")
if p.compare_verbs(word1, word2):
    print("same verb")
if p.compare_adjs(word1, word2):
    print("same adj.")


# ADD CORRECT "a" OR "an" FOR A GIVEN WORD:

print("Did you want ", p.a(thing), " or ", p.an(idea))


# CONVERT NUMERALS INTO ORDINALS (i.e. 1->1st, 2->2nd, 3->3rd, etc.)

print("It was", p.ordinal(position), " from the left\n")

# CONVERT NUMERALS TO WORDS (i.e. 1->"one", 101->"one hundred and one", etc.)
# RETURNS A SINGLE STRING...

words = p.number_to_words(1234)
# "one thousand, two hundred and thirty-four"
words = p.number_to_words(p.ordinal(1234))
# "one thousand, two hundred and thirty-fourth"


# GET BACK A LIST OF STRINGS, ONE FOR EACH "CHUNK"...

words = p.number_to_words(1234, wantlist=True)
# ("one thousand","two hundred and thirty-four")


# OPTIONAL PARAMETERS CHANGE TRANSLATION:

words = p.number_to_words(12345, group=1)
# "one, two, three, four, five"

words = p.number_to_words(12345, group=2)
# "twelve, thirty-four, five"

words = p.number_to_words(12345, group=3)
# "one twenty-three, forty-five"

words = p.number_to_words(1234, andword="")
# "one thousand, two hundred thirty-four"

words = p.number_to_words(1234, andword=", plus")
# "one thousand, two hundred, plus thirty-four"
# TODO: I get no comma before plus: check perl

words = p.number_to_words(555_1202, group=1, zero="oh")
# "five, five, five, one, two, oh, two"

words = p.number_to_words(555_1202, group=1, one="unity")
# "five, five, five, unity, two, oh, two"

words = p.number_to_words(123.456, group=1, decimal="mark")
# "one two three mark four five six"
# TODO: DOCBUG: perl gives commas here as do I

# LITERAL STYLE ONLY NAMES NUMBERS LESS THAN A CERTAIN THRESHOLD...

words = p.number_to_words(9, threshold=10)  # "nine"
words = p.number_to_words(10, threshold=10)  # "ten"
words = p.number_to_words(11, threshold=10)  # "11"
words = p.number_to_words(1000, threshold=10)  # "1,000"

# JOIN WORDS INTO A LIST:

mylist = p.join(("apple", "banana", "carrot"))
# "apple, banana, and carrot"

mylist = p.join(("apple", "banana"))
# "apple and banana"

mylist = p.join(("apple", "banana", "carrot"), final_sep="")
# "apple, banana and carrot"


# REQUIRE "CLASSICAL" PLURALS (EG: "focus"->"foci", "cherub"->"cherubim")

p.classical()  # USE ALL CLASSICAL PLURALS

p.classical(all=True)  # USE ALL CLASSICAL PLURALS
p.classical(all=False)  # SWITCH OFF CLASSICAL MODE

p.classical(zero=True)  #  "no error" INSTEAD OF "no errors"
p.classical(zero=False)  #  "no errors" INSTEAD OF "no error"

p.classical(herd=True)  #  "2 buffalo" INSTEAD OF "2 buffalos"
p.classical(herd=False)  #  "2 buffalos" INSTEAD OF "2 buffalo"

p.classical(persons=True)  # "2 chairpersons" INSTEAD OF "2 chairpeople"
p.classical(persons=False)  # "2 chairpeople" INSTEAD OF "2 chairpersons"

p.classical(ancient=True)  # "2 formulae" INSTEAD OF "2 formulas"
p.classical(ancient=False)  # "2 formulas" INSTEAD OF "2 formulae"


# INTERPOLATE "plural()", "plural_noun()", "plural_verb()", "plural_adj()", "singular_noun()",
# a()", "an()", "num()" AND "ordinal()" WITHIN STRINGS:

print(p.inflect("The plural of {0} is plural('{0}')".format(word)))
print(p.inflect("The singular of {0} is singular_noun('{0}')".format(word)))
print(p.inflect("I saw {0} plural('cat',{0})".format(cat_count)))
print(
    p.inflect(
        "plural('I',{0}) "
        "plural_verb('saw',{0}) "
        "plural('a',{1}) "
        "plural_noun('saw',{1})".format(N1, N2)
    )
)
print(
    p.inflect(
        "num({0}, False)plural('I') "
        "plural_verb('saw') "
        "num({1}, False)plural('a') "
        "plural_noun('saw')".format(N1, N2)
    )
)
print(p.inflect("I saw num({0}) plural('cat')\nnum()".format(cat_count)))
print(p.inflect("There plural_verb('was',{0}) no('error',{0})".format(errors)))
print(p.inflect("There num({0}, False)plural_verb('was') no('error')".format(errors)))
print(p.inflect("Did you want a('{0}') or an('{1}')".format(thing, idea)))
print(p.inflect("It was ordinal('{0}') from the left".format(position)))


# ADD USER-DEFINED INFLECTIONS (OVERRIDING INBUILT RULES):

p.defnoun("VAX", "VAXen")  # SINGULAR => PLURAL

p.defverb(
    "will",  # 1ST PERSON SINGULAR
    "shall",  # 1ST PERSON PLURAL
    "will",  # 2ND PERSON SINGULAR
    "will",  # 2ND PERSON PLURAL
    "will",  # 3RD PERSON SINGULAR
    "will",  # 3RD PERSON PLURAL
)

p.defadj("hir", "their")  # SINGULAR => PLURAL

p.defa("h")  # "AY HALWAYS SEZ 'HAITCH'!"

p.defan("horrendous.*")  # "AN HORRENDOUS AFFECTATION"

描述

模块 inflect.py 中类 engine 的方法提供复数屈折、单数名词屈折、英语单词的“a”/“an”选择以及数字的单词处理。

提供所有名词、大多数动词和一些形容词的复数形式。在适当的情况下,还提供了“古典”变体(例如:“brother” -> “brethren”,“dogma” -> “dogmata”,等等)。

也提供了单数名词的形式。可以选择单数代词的性别(例如“they” -> “it”或“she”或“he”或“they”)。

为所有英语单词以及大多数缩写词提供了基于发音的“a”/“an”选择。

还可以将数字(1,2,3)屈折为序数词(1st,2nd,3rd)和英语单词(“one”,“two”,“three”)。

在生成这些屈折形式时,inflect.py遵循牛津高阶英汉双解大词典和Fowler的现代英语用法指南,在两者不一致时优先选择前者。

该模块以标准英国拼写为基础构建,但设计上也能处理常见的美国变体。俚语、行话和其他英语方言没有明确提供。

对于单个单词存在两个或多个屈折形式(通常是“古典”形式和“现代”形式)时,inflect.py倾向于更常见的形式(通常是“现代”形式),除非指定了“古典”处理(见现代与古典屈折)。

构成复数和单数

屈折复数和单数

所有plural...复数屈折方法都将要屈折的单词作为其第一个参数,并返回相应的屈折形式。请注意,所有这些方法都期望单词的单数形式。传递复数形式的结果是未定义的(且很可能不正确)。同样,si...单数屈折方法期望单词的复数形式。

plural...方法还接受一个可选的第二个参数,该参数指示单词的语法“数量”(或与被屈折的单词必须一致的另一个单词的“数量”)。如果提供了“数量”参数,并且它不是1(或"one""a",或某些其他表示单数的形容词),则返回单词的复数形式。如果“数量”参数确实表示单数,则返回(未屈折的)单词本身。如果省略了数量参数,则无条件地返回复数形式。

si...方法以类似的方式接受第二个参数。如果是数字1的某种形式,或者省略了它,则返回单数形式。否则,返回未更改的复数形式。

inflect.engine的各种方法是

plural_noun(word, count=None)

plural_noun()方法接受一个单数英语名词或代词,并返回其复数形式。名词的领属形式(“I” -> “we”)和宾格形式(“me” -> “us”)被处理,同样还有所有格代词(“mine” -> “ours”)。

plural_verb(word, count=None)

plural_verb()方法接受一个已变形的动词的单数形式(即,已经在正确的“人称”和“语气”),并返回相应的复数形式。

plural_adj(word, count=None)

plural_adj()方法接受某些类型形容词的单数形式,并返回相应的复数形式。正确处理的形容词包括:“数量”形容词(“a” -> “some”),指示形容词(“this” -> “these”,“that” -> “those”),以及所有格形容词(“my” -> “our”,“cat’s” -> “cats’”,“child’s” -> “childrens’”,等等)。

plural(word, count=None)

plural()方法接受一个单数英语名词、代词、动词或形容词,并返回其复数形式。当一个单词的屈折形式取决于其词性(例如,名词“thought”屈折为“thoughts”,动词“thought”屈折为“thought”)时,优先选择(单数)名词意义而不是(单数)动词意义。

因此,plural("knife") 将返回 “knives”(将 “knife” 视为单数名词),而 plural("knifes") 将返回 “knife”(将 “knifes” 视为第三人称单数动词)。

此类情况固有的歧义表明,在已知词性时,应优先使用 plural_nounplural_verbplural_adj,而不是 plural

singular_noun(word, count=None)

方法 singular_noun() 接受一个复数英语名词或代词,并返回其单数形式。处理主格(“we” -> “I”)和宾格(“us” -> “me”)的代词,以及所有格代词(“ours” -> “mine”)。当返回第三人称单数代词时,默认为中性性别(“they” -> “it”),而不是(“they” -> “she”)或(“they” -> “he”)。这可以通过 gender() 进行更改。

请注意,所有这些方法都忽略了围绕被变形的单词周围的任何空白,但在返回结果时保留这些空白。例如,plural(" cat ") 返回 “ cats “。

gender(genderletter)

第三人称复数代词在女性、男性和中性形式上采用相同的形式(例如,“they”)。然而,单数形式取决于性别(例如,“she”、“he”、“it”和“they” – “they” 是中性形式)。默认情况下,singular_noun 返回中性形式,但可以使用 gender 方法选择性别。将性别首字母传递给 gender 以返回单数的 f(eminine)、m(asculine)、n(euter) 或 t(hey) 形式。例如,gender(‘f’) 后跟 singular_noun(‘themselves’) 返回 ‘herself’。

编号复数

plural... 方法仅返回变形的单词,而不返回用于变形的计数。因此,为了产生 “I saw 3 ducks”,有必要使用

print("I saw", N, p.plural_noun(animal, N))

由于产生复数通常的目的是使其与前面的计数一致,inflect.py 提供了一个方法 (no(word, count)),它根据单词和(可选的)计数返回计数后跟正确变形的单词。因此,前面的示例可以重写为

print("I saw ", p.no(animal, N))

此外,如果计数为零(或表示零的其他术语,例如 "zero""nil" 等),则计数被替换为单词“no”。因此,如果 N 的值为零,前面的示例将打印(稍微更优雅的)

I saw no animals

而不是

I saw 0 animals

请注意,该方法的名称是一语双关:该方法返回一个数字(一个 No.)或一个 "no",在变形的单词之前。

减少所需的计数数量

在某些情况下,需要为各种 plural... 方法提供显式的计数,这可能导致重复。例如

print(
    plural_adj("This", errors),
    plural_noun(" error", errors),
    plural_verb(" was", errors),
    " fatal.",
)

因此,inflect.py 提供了一个方法 (num(count=None, show=None)),可用于设置持久的“默认数字”值。如果设置了此类值,则随后在省略可选第二个“数字”参数时使用该值。因此可以调用 num()(不带任何参数)来删除设置的默认值。因此,我们可以重写前面的示例

p.num(errors)
print(p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal.")
p.num()

通常,num() 返回其第一个参数,因此它也可以在类似的情况下“内联”使用

print(p.num(errors), p.plural_noun(" error"), p.plural_verb(" was"), " detected.")
if severity > 1:
    print(
        p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal."
    )

然而,在某些上下文中(请参阅 在字符串中插入变形),最好是 num() 返回一个空字符串。因此,num 提供一个可选的第二个参数。如果提供了该参数(即,如果它已定义)并且评估结果为 false,则 num 返回一个空字符串而不是其第一个参数。例如

print(p.num(errors, 0), p.no("error"), p.plural_verb(" was"), " detected.")
if severity > 1:
    print(
        p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal."
    )

数字不敏感的相等性

inflect.py 还提供了通过以下方法解决不同复数形式的词语比较问题的解决方案:compare(word1, word2)compare_nouns(word1, word2)compare_verbs(word1, word2)compare_adjs(word1, word2)。这些方法中的每一个都接受两个字符串,并使用相应的复数变位方法(分别对应 plural()plural_noun()plural_verb()plural_adj())进行比较。

比较的结果如果以下条件成立则返回 true:

  • 字符串相等,或者

  • 一个字符串等于另一个字符串的复数形式,或者

  • 字符串是同一个词的两个不同复数形式。

因此,以下所有情况都返回 true

p.compare("index", "index")  # RETURNS "eq"
p.compare("index", "indexes")  # RETURNS "s:p"
p.compare("index", "indices")  # RETURNS "s:p"
p.compare("indexes", "index")  # RETURNS "p:s"
p.compare("indices", "index")  # RETURNS "p:s"
p.compare("indices", "indexes")  # RETURNS "p:p"
p.compare("indexes", "indices")  # RETURNS "p:p"
p.compare("indices", "indices")  # RETURNS "eq"

如前一个示例中的注释所示,各种 compare 方法实际返回的值编码了哪个三个相等规则成功:如果字符串相同,则返回 “eq”;如果字符串分别是单数和复数,则返回 “s:p”;如果是复数和单数,则返回 “p:s”;如果是两个不同的复数,则返回 “p:p”。返回空字符串表示不等式。

需要注意的是,两个不同的单数词偶然采取相同的复数形式时不会被考虑为相等,也不是一个(单数)词的复数是另一个(复数)词的单数的情况。因此,以下所有情况都返回 false

p.compare("base", "basis")  # ALTHOUGH BOTH -> "bases"
p.compare("syrinx", "syringe")  # ALTHOUGH BOTH -> "syringes"
p.compare("she", "he")  # ALTHOUGH BOTH -> "they"

p.compare("opus", "operas")  # ALTHOUGH "opus" -> "opera" -> "operas"
p.compare("taxi", "taxes")  # ALTHOUGH "taxi" -> "taxis" -> "taxes"

还要注意的是,尽管比较是“数量无关的”,但它不是“大小写无关的”(即,plural("time","Times") 返回 false。为了同时获得数量和大小写不敏感性,请在两个字符串上都使用 lower() 方法(即,plural("time".lower(), "Times".lower()) 返回 true)。

企业版

作为 Tidelift 订阅的一部分提供。

该项目以及成千上万个其他包的维护者正在与 Tidelift 合作,提供一种企业订阅,涵盖您使用的所有开源软件。

了解更多.

项目详情


发布历史 发布通知 | RSS 源

下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分发

inflect-7.4.0.tar.gz (72.7 kB 查看哈希值)

上传时间

构建分发

inflect-7.4.0-py3-none-any.whl (34.8 kB 查看哈希值)

上传时间 Python 3