ja k tomu taky doiteroval, spis ale jen kvuli citelnosti. Mival jsem tuple tam, kde to mely byt nemenitelne hodnoty - treba parametry predavane do unit testu. Ale nakonec s temi hranatymi zavorkami to je citelnejsi :)
Akorat jsem narazil na ten problem zmineny ve clanku: def neco(x=[]) to je hodne blbe na jazyk (i pro) neprofesionaly
Rozumím snaze posílat si immutable hodnoty, ale tady je v Pythonu nekonzistence - má poměrně neužitečný "frozen set" a tuple jako "zmrzačený/zamrzlý seznam", ale nemá nic jako frozen mapping - snahy s ním přijít byly odmítnuty.
Co se týče toho default parametru, souhlasím, že to je nepříjemné a nemám teď z hlavy nápad, jak to měli udělat vývojáři Pythonu jinak - beru to jako daň dynamičnosti jazyka. Důrazně doporučuju dvě věci:
1. Tohle nepoužívat, nahradit to None a pak, když se ten parametr nevyplní, list zkonstruovat ex post.
2. Používat pro Python důsledně lintery a ideálně více (třeba Ruff a Pyright pro rychlou kontrolu a Pylint pro CI apod.). Konkrétně Pylint tohle ošetřuje:
W0102: Dangerous default value [] as argument (dangerous-default-value)
> (...) že to nutí ke změně typových hintů. Protože pokud tam bude def x(y=None), tak typ toho y už nebude "typ", ale "Optional[typ]".
Pokud je problém v tom Optional
, tak ať funkce bere y: Iterable[T]
, a seznam (=implementaci) si z parametru může vyrobit v těle? Výchozí hodnotou může být bezpečná* n-tice, a jediná nevýhoda, která mě takhle z fleku napadá, je absence
_ = x(None) # explicitly requesting default value
Navíc si myslím, že ta "změněná" sémantika typu je vlastně správně - buď tam x dám (x: T) nebo ne (x: None). Typ x-u je otázkou rozhraní, ne toho, co se skutečně stane-
[*]: Samozřejmě záleží na bezpečnosti všech prvků n-tice... ale pokud už člověk musí udělat něco takového, tak si tu nekonzistenci zaslouží.
>>> first = ("eggs", "ham", ["spam"]*5) >>> second = first + ("baked beans",) >>> second[2].append("spam") # even more spam please >>> len(first[2]) 6
Na druhou stranu by mě zajímal use case takové funkce, která potřebuje zároveň někdy list na vstupu a zároveň někdy tenhle default. Chceme ten list mutovat? Pokud ano, je k něčemu ten implicitně vytvořený? Pokud ne, je problém tam ten prázdný list poslat explicitně? Mně přijdou některé "kreativně" napsané funkce, které třeba někdy mění pole in-place a jindy vrací nové apod. jako jasné antipatterny. Ale třeba máš nějaký příklad, kde to dává výborný smysl...