Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem Python - sdílené parametry metod

Ahoj,

jde nějak udělat, aby byly sdílené parametry jedné metody i u druhé? Jde mi o to, že mám u 4 metod téměř totožné vstupní parametry. Ty 3 další metody volají tu hlavní a posílají tam ty vlastní vstupní argumenty parametrů.

Díky.

Předmět Autor Datum
No a čemu to vadí?
Wikan 02.02.2021 21:39
Wikan
Ono to nevadí až tak, ale těch vstupních prametrů je tam asi 20 a aby to bylo aspoň trochu přehledné…
Peppe 02.02.2021 21:45
Peppe
Tak si těmi parametry náplň nějaký objekt a předávej ten. Podle způsobu použití by se pak možná hodi…
Wikan 02.02.2021 22:00
Wikan
Není to, co jsem si představoval, ale účel to asi splní. Díky za tip. :)
Peppe 02.02.2021 23:19
Peppe
Funkce se 20 vstupnimi parametry? To uz je signal toho, ze ta funkce dela moc veci, asi bych to kapk…
MaSo 03.02.2021 08:13
MaSo
Tak zalezi na tom, co ta funkce dela a co ma za parametry. Celkem bezne potkavam funkce s variabilni…
gilhad 03.02.2021 12:35
gilhad
Neznam python, zivim se Javou. Ale kdyby mi nekdo na code-review predhodil metodu s 20 parametry, ne…
MaSo 03.02.2021 12:43
MaSo
Python neni java. Varargs a pole a slovnik jsou priblizne zamenitelne v tomto kontextu, nekdy je po…
gilhad 03.02.2021 13:58
gilhad
Asi hledas tohle: https://stackoverflow.com/questions/3394835/use-of-args-and-kwargs def MainFunk…
gilhad 03.02.2021 00:31
gilhad
O tomhle jsem taky přemýšlel, ale nepodařilo se mi to pak dál udělat tak, aby to fungovalo, jak potř…
Peppe 03.02.2021 20:56
Peppe
Tady https://ecederstrand.github.io/exchangelib/exchangelib/ vidim def filter(self, *args, **kwargs…
gilhad 04.02.2021 14:12
gilhad
No, to by mohlo fungovat. Vyzkouším, díky. :) poslední
Peppe 06.02.2021 15:20
Peppe

Ono to nevadí až tak, ale těch vstupních prametrů je tam asi 20 a aby to bylo aspoň trochu přehledné, tak je každý parametr na novém řádku. No a když tam jsou ty podobné metody 4, tak se to jednak zbytečně natahuje a jednak je jakákoli úprava parametrů o něco složitější - je to na více místech.

Tak zalezi na tom, co ta funkce dela a co ma za parametry. Celkem bezne potkavam funkce s variabilnim poctem parametru, kde to smysl ma.
Napriklad print.
Nebo generovani formularu, kde se daji jednotlivym polim predavat krome hodnot i html/css/database atributy, kterych jsou na vyber desitky - pokud se predavaji pricetnym zpusobem, muze byt zapis velice citelny a odstrani se predavani slovniku, ktere to jen syntakticky komplikuji, ale funguji stejne.

def return_tag(name,content, **attributes):
......

print return_tag("a" ,"Klikni sem", href="http://example.org/", id="klik", class="clickable enhanced")
print return_tag("img",None, src="http://example.org/pic.jpg", alt="super obrazek", width="100px", height="50px", class="picture normal")

Neznam python, zivim se Javou. Ale kdyby mi nekdo na code-review predhodil metodu s 20 parametry, neproslo by to at by ta funkce delala cokoliv... Funkce s varargs, jsou neco jineho, tam se da v modernich jazycich pouzit spread operator a predavat pole, ale taky to neni buhvico, nelibi se mi to...

Python neni java.

Varargs a pole a slovnik jsou priblizne zamenitelne v tomto kontextu, nekdy je pohodlnejsi a prehlednejsi pouzit ty varargs, odkud si funkce po ceste vyzvedavaji sve specificke parametry a naopak pridavaji jine a ta posledni zpracuje, co zbyde.

Ackoli to jde zapsat ruznymi zpusoby, nekdy je tento prehlednejsi (a jindy zase ne). Povazuju za dobre znat moznosti jazyka i do extremu, ale pouzivat je spis umirnene, pokud to neznamena vyrazne zeslozitit kod.

Treba ten muj priklad s html tagama samozrejme jde prepsat pro predavani pole (a to pole nekde vytvorit), nebo dokonce immutable objektu (a ten nekde vytvorit a definovat), ale IMHO takovyto zapis je zrovna v tomto pripade prehlednejsi.

A pokud by nekde niz v print_tag byla funkce na manipulovani treba tech class, tak muze mit v hlavicce (... class="", **kwargs) a rovnou se vi, ze zrovna tahle funkce asi ty class nejak pouziva a zbytek asi proste preposila dal v retezci volani. Zatimco jine funkce se class zabyvat nemusi a jen ji predavaji, pokud je. U nekterych frameworku tento pristup dava velky smysl a vyrazne zvysuje citelnost.

Asi hledas tohle:

https://stackoverflow.com/questions/3394835/use-of-args-and-kwargs



def MainFunkce(a,b,c, adam="", beta="",cyril=""):
   print ("a=%s; b=%s; c=%s; adam=%s; beta=%s; cyril=%s" % (a,b,c, adam, beta,cyril))

def Funkce1(*args,**kwargs): 
    MainFunkce(1,*args,beta="BB",**kwargs)

Funkce1(2,3, cyril="CC", adam="AA")

a=1; b=2; c=3; adam=AA; beta=BB; cyril=CC

def Funkce2(*p1,**p2): 
    MainFunkce(*p1,**p2)

Funkce2(1,2,3, cyril="CC", adam="AA", beta="BB")

a=1; b=2; c=3; adam=AA; beta=BB; cyril=CC


O tomhle jsem taky přemýšlel, ale nepodařilo se mi to pak dál udělat tak, aby to fungovalo, jak potřebuju.

Ještě se trochu rozepíšu. Třeba někoho napadne elegantnější řešení.

Dělám wrapper pro zjednodušení práce s maily exchangelib knihovny. Mám tam metodu pro iteraci inbox složky, metoda přijímá základní údaje pro přihlášení do schránky (jméno, heslo, doménu, exchange server a certifikát). Ve skutečnosti se dá volat metoda i bez jakýchkoli argumentů - v tom případě se do metody dotáhnou údaje z config.ini souboru, který slouží k podobných účelům.
Tyto údaje se dál předají privátní metodě, které vytvoří objekt účtu a vrátí ho zpět. A nyní nastupuje dalších asi 20 parametrů pro pokročilé filtrování konkrétních mailů:

subject__exact: Union[list, str] = None,
subject__iexact: Union[list, str] = None,
subject__contains: Union[list, str] = None,
subject__icontains: Union[list, str] = None,
subject__startswith: Union[list, str] = None,
subject__istartswith: Union[list, str] = None,
subject__endswith: Union[list, str] = None,
subject__iendswith: Union[list, str] = None,

A to samé pro pár dalších nejčastějších údajů v mailu. Důvod, proč to tam tak dávám je, že chci, aby to PyCharm napovídal. Sám když takto připravuju ten wrapper, tak ta knihovna exchange je buď nějak špatně vnitřně dokumentovaná nebo nevím, ale musím jet podle dokumentace na webu, protože Pycharm mi tyhle pokročilé věci nenapovídá.
Původně jsem tohle zkoušel pár jinými způsoby, ale skončil jsem u tohoto otrockého způsobu, protože přechozí pokusy nefungovaly. Slovník jsem si předávat zkoušel, ale když jsem chtěl udělat něco na způsob:

lookups = {'subject__exact': 'nejaky_predmet123', 'sender__email_address__icontains': 'MUJmail@'}
all_mails = acount.inbox.all()
for lookup in lookups:
    all_mails.filter(exec(f'{lookup}={lookups[lookup]}'))

Bohužel ani exec() ani eval() zřejmě neumí string převést na název parametru, takže mi to pořád házelo chybu. Skončilo to u dlouhého if bloku, kde postupně kontroluju, jestli je daný parametr zadán a pokud ano, pak to filteruju takto natvrdo:

if subject__exact is not None:
    all_mails.filter(subject__exact=subject__exact)

Podobných metod pro zjedušejí práce s mailem tam je víc a každá má všechny tyhle pokročilé filtrovací parametry. Pak tam je právě ta hlavní, kam předám objekt konkrétní složky schránky, všechny tyto parametry, ta to vyfiltruje a předá objekt zpět. Poté se z objektu jen iterují vyfiltrované maily.

Je jasné, že to možná zbytečně složité, ale zatím jediné funkční řešení. Nemáte někdo nápad, jak to zjednodušit? Ještě jednou zopakuju, že je to opravdu jen wraper pro zjednodušení a chci, aby dostupné parametry byly napovídány. :-)

Díky.

Zpět do poradny Odpovědět na původní otázku Nahoru