Как привести слова к одному виду?

Допустим есть 2 слова. собаку и кошка. Я хочу чтобы второе слово взяло теги первого. Чтобы на выходе получилось кошку.

Что попробовал

s1 = morph.parse(word1)[0] #собаку
s2 = morph.parse(word2)[0] #кошка

s3= s2.inflect({s1.tag.POS,s1.tag.case,s1.tag.number})

На выходе у нас кошку. С существительными работает. А вот если взять идти и шагал то тут всё рушится, так как у первого нет tag.case и tag.number.

Вопрос. Можно ли сделать что примерно такого

s3= s2.inflect({s1.tag})

Чтобы оно автоматом брало все теги из первого


Ответы (1 шт):

Автор решения: insolor

Свойство tag имеет класс OpencorporaTag, при передаче в метод inflect будет ругаться, что сравнение <= не поддерживается между объектами 'OpencorporaTag' и 'frozenset' (TypeError: '<=' not supported between instances of 'OpencorporaTag' and 'frozenset'). То есть нужно из объекта OpencorporaTag из вытащить набор граммем в виде множества (set или frozenset), для этого нужно обратиться к свойству grammemes:

import pymorphy2

morph = pymorphy2.MorphAnalyzer()

word1 = "собаку"
word2 = "кошка"

s1 = morph.parse(word1)[0]
s2 = morph.parse(word2)[0]

s3 = s2.inflect(s1.tag.grammemes)

print(s3.word)  # Вывод: кошку

# ----

word1 = "идти"
word2 = "шагал"

s1 = morph.parse(word1)[0]
s2 = morph.parse(word2)[0]

s3 = s2.inflect(s1.tag.grammemes)

print(s3.word)  # Вывод: шагать

Для слов с неоднозначностью может возникать ошибка. Например для слова "стали" без контекста не понятно, что это - существительное и глагол. Поэтому в идеале нужно учитывать не только первый разбор, а все разборы обоих слов.

Ниже пример, где учитываются все варианты разбора слова "стали":

import pymorphy2

morph = pymorphy2.MorphAnalyzer()

word1 = "стали"
word2 = "кошка"

s2 = morph.parse(word2)[0]

for s1 in morph.parse(word1):
    gramemmes = set(s1.tag.grammemes)
    
    if 'NOUN' in s2.tag:
        # Для существительных убираем одушевленность и род, т.к. это не категории формы, а характеристика самого слова
        # Например "кошка" всегда одушевленное, а "сталь" всегда неодушевленное,
        # а слово "день" нельзя перевести в женский род при всем желании
        gramemmes -= {'inan', 'anim', 'femn', 'masc', 'neut'}
    
    s3 = s2.inflect(gramemmes)
    if s3 is not None:  # Если удалось просклонять, результат выводим
        print(gramemmes)
        print(s3.word)

Вывод:

{'sing', 'gent', 'NOUN'}
кошки
{'nomn', 'plur', 'NOUN'}
кошки
{'sing', 'datv', 'NOUN'}
кошке
{'sing', 'loct', 'NOUN'}
кошке
{'accs', 'plur', 'NOUN'}
кошек

В принципе результаты с одинаковой формой можно объединять (если их записывать в set), тогда получится три варианта: кошки, кошке, кошек

→ Ссылка