Design třídy... – Python – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Design třídy... – Python – Fórum – Programujte.comDesign třídy... – Python – Fórum – Programujte.com

 

oxidián0
Grafoman
1. 10. 2024   #1
-
0
-

Tak zatímco předchozí vlákno jsem úspěšně vyřešil, třídu pro self.transpose jsem vytvořil, přemýšlím nad přehledností a jednoduchostí původní třídy. Nejprve seznámíme publikum co bylo cílem kódu. Původní myšlenka byla: ze zkopírovaného textu s konjugačních tabulek získat koncovky ke kořenům. To se taky děje. Ale pak jsem zavedl třídu Transpose abych získal nové možnosti - metody.

Mám takovýto kód

if check_add_unique:
    parser.print_unique_koncovky(sort)
else:
    parser.transpose.print_column("Indicative", "Present", True)

Je-li check_add_unique True, pak získám přibližně podobný výpis:

explicar|explic|o|aba|aría|aré|as|aste|abas|arías|arás|a|ó|ará|amos|ábamos|aríamos|aremos|áis|asteis|abais|aríais|aréis|an|aron|aban|arían|arán|ara|ase|are|aras|ases|ares|áramos|ásemos|áremos|arais|aseis|areis|aran|asen|aren|ad|ando|ado|ar
explicar|expliqu|é|e|es|emos|éis|en

tento výpis vzniká velmi jednoduše během parsování txt tabulky po řádcích.

Přitom původní tabulky vypadají přibližně takto:

Indicative of "explicar"
Irregularities are in red
	
Present
	
Preterite
	
Imperfect
	
Conditional
	
Future
yo	
explico
expliqué
explicaba
explicaría
explicaré
tú	
explicas
explicaste
explicabas
explicarías
explicarás
él/ella/Ud.	
explica
explicó
explicaba
explicaría
explicará
nosotros	
explicamos
explicamos
explicábamos
explicaríamos
explicaremos
vosotros	
explicáis
explicasteis
explicabais
explicaríais
explicaréis
ellos/ellas/Uds.	
explican
explicaron
explicaban
explicarían
explicarán

Nejsložitější je metoda def parse_line(self, line) s tou není nutné vás seznamovat.

Nastavuje celou řadu vlastností na základě toho co zrovna na daném řádku naleznu. Je li to slovo označující název konjugační tabulky, nebo čas, nebo zájmeno, apod. tak z toho vyvodím určitý závěr a udržuji přehled pomocí vlastností jako self.column_counter ...

V metodě se nakonec volá metoda

self.add_form_to_kmen(line)

čímž se jednoduše přidá koncovka k danému seznamu.

Jelikož toto parsování bylo původně co nejjednodušší, a třídu Transpose se strukturovaným kontejnerem na data jsem vytvořil později, tato metoda a tato třída nemá strukturované ukládání dat.

Začíná takto:

    def add_form_to_kmen(self, sword):
        preceding_words = []  # Proměnná na uložení slov, 


preceding_words zjišťuje jestli se před daným slovesem vyskytují nějaké jiné slova jako různé formy slovesa mít nebo být nebo zápor a to se ukládá sem. Takže z toho je vidět, že to opravdu není strukturované.

Dále tam mám takový blok if check_add_unique:, který se snaží podívat do pole self.verb_forms[kmen] abych zjistil jestli se koncovka neopakuje... abych prostě zmenšil počet prvků v poli. Tento přidávací blok vypadá takto:

                self.verb_forms_check[kmen] += 1 # Počítám kolik koncovek jsem přidal
                self.verb_forms[kmen].append(sword)
                self.verb_forms_precedes[kmen].append(preceding_string)  # Přidáme předcházející slova
                return True
            self.verb_forms_check[kmen] += 1 # Počítám kolik koncovek jsem přidal
            self.verb_forms[kmen].append(koncovka)

Na a mě napadlo, že kdybych to chtěl dále rozšiřovat a mít metody, které vyfiltrují třeba jen určitou konjugační tabulku nebo jen řádky pro určitou osobu, tak to vlastně nejde, protože nepoužívám žádný strukturovaný kontejner jako v případě self.Transpose ... musel bych tedy tyto speciální parametry přidávat přímo do té metody add_form_to_kmen plus ještě vytvořit přídavné pole, které by shromažďovalo informace o osobě a názvu konjugační tabulky (filtrovat čas by možná ani nešlo - nebo šlo, ale složitě).

Tato třída VerbParser např. obsahuje tyto vlastnosti:

class VerbParser: def __init__(self, sloveso, hledane_kmeny):

        self.verb_forms = {kmen: [] for kmen in hledane_kmeny}
        self.verb_forms_precedes = {kmen: [] for kmen in hledane_kmeny} # Toto je kontejner na slovíčka, která nejsou součástí kmene zpracovávaného slovesa, nutno sbírat i prázdné výskyty.
        self.verb_forms_check = {kmen: 0 for kmen in hledane_kmeny} # data o tom kolik je tam záznamů - !!! Také slovo bez koncovky se počítá do verb_forms_check jako jeden z tvarů
        self.verb_no_form = {kmen: False for kmen in hledane_kmeny} # data o tom zda se daný kmen nachází na řádku v identické podobě bez koncovky
        self.verb_forms_dupl_ignored = 0

z těch polí pak dokážu provést výpis.... Což je něco na tomto principu:

    def print_unique_koncovky(self, sort):
        """Vypíše kmeny s nalezenými koncovkami tak aby se neopakovaly stejné koncovky na jednom řádku."""
        if sort:
            locale.setlocale(locale.LC_ALL, 'es_ES.utf8')
        with open(output_file, "w") as file:
            for kmen, koncovky in self.verb_forms.items():
                line_out = f"{self.sloveso}|{kmen}|"
                
                # Pro každou koncovku zkontroluj, jestli už není v line_out
                if sort:
                    mkoncovky = sorted(koncovky, key=locale.strxfrm)
                else:
                    mkoncovky = koncovky
                for koncovka in mkoncovky:
                    # Kontrola, zda se již daná koncovka v řetězci nevyskytuje
                    if f"|{koncovka}|" not in line_out and not line_out.endswith(f"|{koncovka}"):
                        line_out += f"{koncovka}|"

Je mi jasné, že se používají dva odlišné způsoby práce s daty. Jeden je surové parsování, nasbíráni do pole a druhý je strukturovaný, kde je více možností. U tohoto nestrukturovaného to moc nejde. První věc asi by každého napadlo to předělat vytvořit kontejner se strukturovanými daty něco jako mám u Transpose:

# Pomocná třída, která umožňuje zjistit více informací o hotovém tvaru (stringu)
class SimpleVerbInfo:
    def __init__(self, adverb, person):
        self.adverb = adverb
        self.person = person # 1-6
    def __repr__(self):
        return f"VerbInfo(adverb={self.adverb}, person={self.person})"

class VerbInfo:
    def __init__(self, adverb, preceding, person):
        self.adverb = adverb
        self.preceding = preceding
        self.person = person # 1-6
    def __repr__(self):
        return f"VerbInfo(adverb={self.adverb}, preceding={self.preceding}, person={self.person})"
class Transpose():
        # Časy které neobsahují text před konjugací
        self.simple_times = [ "Indicative", "Subjunctive" ]
        # Definujeme relevantní časy pro každou konjugaci pro kontejner stringů
        self.conjugations = {
            "Indicative": {time: [] for time in ["Present", "Preterite", "Imperfect", "Conditional", "Future"]},
            "Subjunctive": {time: [] for time in ["Present", "Imperfect", "Future"]},
            "Imperative": {time: [] for time in ["Affirmative", "Negative"]},
            "Progressive": {time: [] for time in ["Present", "Preterite", "Imperfect", "Conditional", "Future"]},
            "Perfect": {time: [] for time in ["Present", "Preterite", "Imperfect", "Past", "Conditional", "Future"]},
            "Perfect Subjunctive": {time: [] for time in ["Present", "Past", "Future"]},
            "Informal Future": {"Informal Future": []}  # Specifické jen pro Informal Future
        }
        
        # Definujeme předcházející řetězce jen pro relevantní informace ke stringu
        self.container = {
            "Indicative": {time: [] for time in ["Present", "Preterite", "Imperfect", "Conditional", "Future"]},
            "Subjunctive": {time: [] for time in ["Present", "Imperfect", "Future"]},

            "Imperative": {time: [] for time in ["Negative"]},  # Předcházející stringy jen u negativního imperativu
            "Progressive": {time: [] for time in ["Present", "Preterite", "Imperfect", "Conditional", "Future"]},
            "Perfect": {time: [] for time in ["Present", "Preterite", "Imperfect", "Past", "Conditional", "Future"]},
            "Perfect Subjunctive": {time: [] for time in ["Present", "Past", "Future"]},
            "Informal Future": {"Informal Future": []}
        }

Ovšem tím by se zase zesložitil kód a bylo by to předělávání již funkčního kódu. První věc co mě napadla: izolovat parsování od metod pro výpis dat (tím že bych zavedl kontejner), ale zase se mi do toho nechce, protože původní myšlnenka byla přece jednoduchá, jen nasbírat ty koncovky jako jsem ukázal na začátku. Proč to tedy přeplácávat? Současně ale láká možnost použít další metodu, pomocí které jednoduše má člověk možnost vytisknout si jen tvar pro určité sloveso u dané osoby nebo např. jen pro Subjunktiv či jen pro Perfect.

Šly byste cestou přidávání polí jako

self.verb_forms
self.verb_forms_precedes = {kmen: [] for kmen in hledane_kmeny}
self.verb_forms_check = {kmen: 0 for kmen in hledane_kmeny}
self.verb_no_form = {kmen: False for kmen in hledane_kmeny}

nebo byste našly nějaké třetí řešení, medium difficulty approach?

Pro easy difficulty approach stačí pole typu:
{kmen: [] for kmen in hledane_kmeny}
ovšem pro každou koncovku (respektive pro každý neunikátní tvar) se musí sbírat název tabulky ... což znamená že se to tam bude opakovat třeba 30x.

Nebo třeba medium approach mít jen jedno přídavné pole s informacema, kde bude podobná třída jako VerbInfo,

Tedy asi takto?

class VerbInfo:
    def __init__(self, adverb, preceding, person):
        self.adverb = adverb
        self.preceding = preceding
        self.conjugation = conjugation
        self.no_form = no_form
        self.person = person # 1-6
        self.check = check
    def __repr__(self):
        return f"VerbInfo(adverb={self.adverb}, conjugation={self.conjugation}, preceding={self.preceding}, no_form={self.no_form}, person={self.person}, check={self.check})"
Nahlásit jako SPAM
IP: 94.113.182.–
peter
~ Anonymní uživatel
4016 příspěvků
2. 10. 2024   #2
-
0
-

Podle toho txt mi to prijde cele jako blbost. Nemuzes pri casovani pouze doplnovat koncovku. Leda bys mel slovnicek slov, kde to odpovida tomu vzoru. V opacnem pripade tam muzes mit treba uplne jina slovo. A tvuj parser by to jine slovo pouzil jako koncovku k zakladu slova :)
ja "jsem", ty "jsi", on "byl"
js|em|i|byl => jsem, jsi, jsbyl :)
 

Nahlásit jako SPAM
IP: 2001:718:2601:258:a15a:c9b2:19a4:12cf...–
oxidián0
Grafoman
2. 10. 2024   #3
-
0
-

Peter, celé je to jednodušší než si myslíš.

hledane_kmeny - uživatel si nastaví takové kmeny, které se budou hledat pro dané sloveso. Jelikož v tabulkách je jen jedno sloveso, tak v případě španělštiny existují obvykle jen dva nebo tři kmeny. Např. explic a expliq . To jsou dva údaje na dva řádky samostatně.
Situace s češtinou by byla taková:
js|em|i|me|te|ou
je
byl|a|o
to by bylo unikátní hledání koncovek, toto pro metodu, která vypíše koncovky což je primární cíl. Díky tomu budu moci z toho vytvořit regexy a pak napsat skript na hledání sloves, ale to je jiný topic. Tento skript je psaný pro španělštinu, ale v případě češtiny by to fungovalo podobně tedy řešil bych alternativní možnost parseru dodatečně vypsat některé tvary jen pro učitý čas/způsob např. subjuntive:

šel
šl|a|i|y|o

Nahlásit jako SPAM
IP: 94.113.182.–
peter
~ Anonymní uživatel
4016 příspěvků
3. 10. 2024   #4
-
0
-

Ok, jen jsem byl zvedavy. Mne si nevsimej, ja jsem takovy stoural :)

Nahlásit jako SPAM
IP: 2001:718:2601:258:a15a:c9b2:19a4:12cf...–
oxidián0
Grafoman
3. 10. 2024   #5
-
0
-

Peter, OK, tak já to udělám tak jak jsem říkal (medium difficulty solution), že dám do pole tu "strukturu", definovanou pomocí třídy, nebo jak se tomu správně říká. Místo toho abych ukládal přímo název tabulky, bych mohl ukládat jen index pro self.table_names.

Nahlásit jako SPAM
IP: 94.113.182.–
Zjistit počet nových příspěvků

Přidej příspěvek

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 3 hosté

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý