Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: dustin 17. 06. 2017, 12:46:50
-
Nedávno tu proběhla debata o pozici pythonu jako kvalitním programovacím jazyku. Mohu tedy poprosit místní gurus o úplně základní radu?
Jsem javista. Doma dělám na soukromém projektu v pythonu, protože už mám nějaký kód z dřívějška a (zatím) se mi to nechce přepisovat do javy. Používám pycharm, python 3.4 v Mintu 18.
Snažím se psát objektově, protože jsem na to zvyklý. Současně mám rád v jednom souboru jednu "public" třídu (může obsahovat i "privátní", které se nepoužívají jinde). Samozřejmě chci používat v maximální míře typehinty, abych se v kódu vyznal a maximálně využil možnosti IDE. Bohužel typehinty vyžadují importy a vedou přímo na zakázané circular importy. Diskuse bez rozumného závěru je např. https://github.com/python/typing/issues/105 , https://stackoverflow.com/questions/39740632/python-type-hinting-without-cyclic-imports .
Doporučuje se:
forward reference jako string - i pro tu chce IDE import statement, aby věděl, kde to najít
import xxxxxx bez from a v kódu použít celou cestu - mám projekt ve vnořených modulech, abych to měl aspoň trochu rozdělené. Typehinty jsou pak hodně dlouhé - lze to prosím nějak naaliasovat, abych pokaždé nemusel uvádět celou cestu?
I tak mi to nefunguje - příklad:
Modul ui (s __init__.py) -> soubor webui.py -> class WebUI.
Ve stejném adresáři chci ve třídě ui/webapp.py-> class WebApp v metodě volané zvenku označit typehintem třídu WebUI. Ta ale vytváří instanci třídy WebApp, tudíž samozřejmě má soubor webap.py importovaný.
Zkusím standardní import:
from uis.webui import WebUI
...
def main(self, webui: WebUI):
Klasický circular import vzniklý pouhým typehintováním WebUI, nogo.
Dobře, zkusím variantu pouhého importu
import ui.webui
...
def main(self, webui: uis.webui.WebUI):
Výsledkem je
AttributeError: module 'uis' has no attribute 'webui'
Samozřejmě mohu nic neimportovat, WebUI dát jako string, ignorovat chybu IDE, že daný typ nezná a rezignovat na jakékoliv nabídky proměnných atd. Takový vývoj je mi však silně proti srsti.
Mohu poprosit o zkušenosti, jak v praxi řešíte typehinty a circular importy? Předem díky moc.
-
Oprava příspěvku - ten modul se jmenuje uis (adresář uis), tedy nefunkční import je správně:
import uis.webui
"ui" je jenom překlep na několika místech v needitovatelném příspěvku.
-
Aha, pro tohle je určena podmínka
if TYPE_CHECKING:
from xxxx import yyyy
https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING
Nic moc, protože to IDE negeneruje samo (narozdíl od importu), tudíž se na to bude zapomínat. Ale budiž, dá se.
-
Nesvazovat mixiny s konkrétním typem, ale s rozhraním.
https://stackoverflow.com/questions/39740632/python-type-hinting-without-cyclic-imports/39741253#39741253
-
Interfacy mají také typehinty, co když bude smyčka v deklaracích svých metod (AInterface má metodu s parametrem typu BInterface a naopak)? Jak to pak vyřeší interfacy místo konkrétních implementací? Ten hack s podmíněným importem jo, do mi dává smysl.
-
Interfacy mají také typehinty, co když bude smyčka v deklaracích svých metod (AInterface má metodu s parametrem typu BInterface a naopak)? Jak to pak vyřeší interfacy místo konkrétních implementací? Ten hack s podmíněným importem jo, do mi dává smysl.
V AInterface se volá metoda z BInterface s parametrem AInterface? Pokud ne, tak bych tu metodu dal do jiného interface a odstranil závislost BInterface na AInterface.
-
Protokoly všechny problémy s importy docela dobře řeší
https://www.python.org/dev/peps/pep-0544/
bude to součástí 3.7., ale můžete to používat už teď.
https://www.python.org/dev/peps/pep-0544/#implementation
-
Ten text jsem jenom prolétl. Pokud jsem to pochopil, řeší problém s circular importem, pokud by všechny mé třídy měly předpisy protokoly a jako typy bych používal je (protože se údajně nemusí importovat). To mi přijde ještě daleko nepraktičtější, než typehintové importy dát do if TYPE_CHECKING, což funguje OK.
-
Ten text jsem jenom prolétl. Pokud jsem to pochopil, řeší problém s circular importem, pokud by všechny mé třídy měly předpisy protokoly a jako typy bych používal je (protože se údajně nemusí importovat). To mi přijde ještě daleko nepraktičtější, než typehintové importy dát do if TYPE_CHECKING, což funguje OK.
v místě, kde byste musel jen kvůli typu použít cirkulární import, si místo něho můžete definovat protokol. Asi není třeba to používat všude.
-
To mohu, ale přece nebudu dodělávat protokoly zpětně u některých víceméně náhodně vybraných tříd (kde zrovna došlo k circular importu). Ty by měly sloužit k něčemu koncepčnímu, ne k zpětnému řešení nedokonalosti ekosystému jazyka (type hinty dolepené později + IDE vyžadující importy, aby se v tom vyznalo). To je větší hack, než stejným pracným a hloupým postupem spustit/chyba/opravit přesunut kolizní importy do type-checking podmínky.
-
Nedávno tu proběhla debata o pozici pythonu jako kvalitním programovacím jazyku.
Myslím, že po pár příspěvcích je jasné, že to bylo asi myšleno jen jako vtip. Na skriptíky pro admina je to jazyk velmi dobrý, ale na vývoj to není.
-
Python není Java tak se tam nesnaž naroubovat něco co používáš v Javě.
-
...
Myslím, že po pár příspěvcích je jasné, že to bylo asi myšleno jen jako vtip. Na skriptíky pro admina je to jazyk velmi dobrý, ale na vývoj to není.
;D :D :)
Javamane?
-
...
Myslím, že po pár příspěvcích je jasné, že to bylo asi myšleno jen jako vtip. Na skriptíky pro admina je to jazyk velmi dobrý, ale na vývoj to není.
;D :D :)
Javamane?
nebo lopato...
-
Python není Java tak se tam nesnaž naroubovat něco co používáš v Javě.
Nejde o javu, ale o typy. Nedovedu si představit, jak efektivně vyvíjet projekt už o pár desítkách tříd bez typů. Očividně to pálí spoustu lidí, když v poslední době vzniklo několik na sebe navazujících PEPů, které se to nějakým způsobem snaží řešit.
Jinak se mi python docela líbí, hlavně má pěkné snadno použitelné knihovny pro linux, které ve svém projektu výhodně využiji (udev, alsa, integrace s mpv/mopidy, atd.). Ale je pravda, že kdybych nyní začal od nuly, už bych do něj nešel, ta slabá možnost refaktorizace a dost syrové type hinty v IDE (pycharm) dost zdržují.
-
Myslím, že po pár příspěvcích je jasné, že to bylo asi myšleno jen jako vtip. Na skriptíky pro admina je to jazyk velmi dobrý, ale na vývoj to není.
Vidím to tak nějak stejně. Skriptíky se v něm píšou perfektně, není potřeba žádný build systém, mohu krokovat, ladit, paráda. Ale na složitější projekt mi to nejpřijde dostatečně robustní. I když v poslední době se to posouvá (typelib, abc pro abstraktní metody/třídy, atd.), jen to chce ještě pár verzí a jejich dobrou podporu v IDE (i když např. pycharm je v podpoře beta vlastností docela dopředu, stejně jako jeho sestra Idea v javě).
-
Nejde o javu, ale o typy. Nedovedu si představit, jak efektivně vyvíjet projekt už o pár desítkách tříd bez typů. Očividně to pálí spoustu lidí, když v poslední době vzniklo několik na sebe navazujících PEPů, které se to nějakým způsobem snaží řešit.
Cirkulárním závislostem se lze většinou vyhnout jiným rozvržením kódu. Vůbec není nutné mít každou třídu ve zvláštním souboru. To je omezení Javy.
-
Rozdělení tříd do více souborů má spoustu praktických výhod - snáze se hledají, je snazší si otevřít třídy ve více panelech vedle sebe v IDE (mám vždy dva editační panely), soubory jsou krátké a přehledné. Snáze se také v rámci jednoho souboru vyhledává/nahrazuje - je to v rámci jedné třídy. Rovněž commity v GITu jsou přehlednější, protože už z výpisu změněných souborů v diffu vidím, jakých tříd se týkal. IMO je soubor na public třídu užitečný způsob.
V některých souborech mám několik spolu úzce souvisejících tříd, ale jen pokud jsou krátké, většinou jen pomocná DTO. Navíc třídy v jednom souboru musí jít ve správném pořadí, jak jsou postupně definované - i tak musí být typehinty uvedené jako stringy v apostrofech. Když se na to zapomene - opět se to zjistí až při prvním spuštění, IDE nic nezahlásí, protože třídu zná, zatímco interpret ne.
-
Ještě jsem zapomněl na zásadní přínos rozdělení do souborů - zatím jsem nepotkal IDE, které by nabízelo commit jednotlivých hunků v souboru, ale vždy jeho všechny změny. Takže granularita commitu přes IDE je soubor. Velice často dochází k tomu, že se smíchají dvě změny, které se ale týkají různých tříd. U malých souborů je v IDE commit snadný. Kdybych měl všechny třídy v jednom souboru (zrovna jednu takovou externí knihovnu používám), bylo by commitování přes interaktivní add -i o dost pracnější (nebo bych musel používat nějaký externí GUI nástroj).
-
Ještě jsem zapomněl na zásadní přínos rozdělení do souborů - zatím jsem nepotkal IDE, které by nabízelo commit jednotlivých hunků v souboru, ale vždy jeho všechny změny. Takže granularita commitu přes IDE je soubor. Velice často dochází k tomu, že se smíchají dvě změny, které se ale týkají různých tříd. U malých souborů je v IDE commit snadný. Kdybych měl všechny třídy v jednom souboru (zrovna jednu takovou externí knihovnu používám), bylo by commitování přes interaktivní add -i o dost pracnější (nebo bych musel používat nějaký externí GUI nástroj).
emacs+magit to umí.
-
To je dobře. Již roky doufám, že IntelliJ hunky do svého portfolia doplní, v jejich IDE by se sakra hodily. Ale i tak je daleko rychlejší vybrat celý soubor, než označovat hunky diffu. Občas to dělám v terminálu, nic moc. A proto zůstanu u hodně souborů s minimální velikostí, než doufat, že jsem na nějaký hunk do commitu nezapomněl.
-
To je dobře. Již roky doufám, že IntelliJ hunky do svého portfolia doplní, v jejich IDE by se sakra hodily. Ale i tak je daleko rychlejší vybrat celý soubor, než označovat hunky diffu. Občas to dělám v terminálu, nic moc. A proto zůstanu u hodně souborů s minimální velikostí, než doufat, že jsem na nějaký hunk do commitu nezapomněl.
v PyCharmu už to bude brzy https://youtrack.jetbrains.com/issue/IDEA-63201
tohle by neměl být problém dopsat, kdyby byl git plugin spravován komunitou, tak už by to někdo dávno udělal.
-
Výborně, díky. Mohu jen citovat poslední příspěvek: +1 After 7 years, it is happening!