Jak uniknąć importu kołowego w Pythonie? [duplikat]
To pytanie ma już odpowiedź tutaj:
- Circular import zależność w Pythonie 5 odpowiedzi
Wiem, że kwestia importu kołowego w Pythonie pojawiała się już wiele razy i czytałem te dyskusje. Komentarz, który jest wielokrotnie w tych dyskusjach jest to, że okrągły import jest oznaką złego projektu i Kod powinien być zreorganizowane, aby uniknąć przywozu okrężnego.
Mógłby mi ktoś powiedzieć jak w takiej sytuacji uniknąć importu kołowego?: Mam dwie klasy i chcę, aby każda klasa miała konstruktor (metodę), który pobiera instancję drugiej klasy i zwraca instancję klasy.
Dokładniej, jedna klasa jest zmienna, a jedna niezmienna. Potrzebna jest klasa niezmienna do hashowania, porównywania i tak dalej. Klasa mutable jest również potrzebna do robienia rzeczy. Jest to podobne do zestawów i frozensets lub do list i krotek.
Mógłbym umieścić obie definicje klas w tym samym module. Czy są jakieś inne sugestie?
Przykładem zabawki byłaby Klasa A, która ma atrybut, który jest listą, i Klasa B, która ma atrybut, który jest krotką. Następnie Klasa A ma metodę, która pobiera instancję klasy B i zwraca instancję klasy a (poprzez konwersję krotki na listę) i podobnie Klasa B ma metodę, która pobiera instancję klasy A i zwraca instancję klasy A Klasa B (poprzez konwersję listy na krotkę).
3 answers
Importuj tylko moduł, nie Importuj z modułu:
Rozważmy a.py
:
import b
class A:
def bar(self):
return b.B()
I b.py
:
import a
class B:
def bar(self):
return a.A()
To działa idealnie.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-07 15:55:37
Rozważ następujący przykładowy pakiet Pythona, w którym a.py
i b.py
zależą od siebie:
/package
__init__.py
a.py
b.py
Istnieje kilka sposobów na zaimportowanie modułu w Pythonie
import package.a # Absolute import
import package.a as a_mod # Absolute import bound to different name
from package import a # Alternate absolute import
import a # Implicit relative import (deprecated, py2 only)
from . import a # Explicit relative import
Niestety, tylko 1. i 4. opcje faktycznie działają, gdy masz okrągłe zależności (reszta podnosi ImportError
lub AttributeError
). Ogólnie rzecz biorąc, nie powinieneś używać 4. składni, ponieważ działa ona tylko w python2 i naraża się na zderzenie z innymi modułami innych firm. Tak naprawdę, tylko pierwszy składnia jest gwarantowana. Jednak nadal masz kilka opcji, gdy masz do czynienia z zależnościami kołowymi.
EDIT: problemy
ImportError
iAttributeError
występują tylko w python 2. W Pythonie 3 Maszyna importowa została przepisana i wszystkie z tych poleceń importu (z wyjątkiem 4) będzie działać, nawet z zależności kołowe.
Użyj Importu Bezwzględnego
Po prostu użyj pierwszej składni importu powyżej. Minusem tej metody jest to, że import nazwy mogą uzyskać super długie dla dużych pakietów.
W a.py
import package.b
W b.py
import package.a
Odroczyć import na później
Widziałem tę metodę używaną w wielu pakietach, ale nadal wydaje mi się to trudne, i nie podoba mi się, że nie mogę spojrzeć na górę modułu i zobaczyć wszystkich jego zależności, muszę przejść przeszukanie wszystkich funkcji, jak również.
W a.py
def func():
from package import b
W b.py
def func():
from package import a
Umieścić wszystkie import w centralnym moduł
To również działa, ale ma ten sam problem co pierwsza metoda, gdzie wszystkie wywołania pakietu i podmodułu otrzymują super długie . Ma również dwie główne wady-zmusza wszystkie moduły podrzędne do zaimportowania, nawet jeśli używasz tylko jednego lub dwóch, a nadal nie możesz spojrzeć na żadne z modułów podrzędnych i szybko zobaczyć ich zależności na górze, musisz przejść do przesiewania funkcji.
W __init__.py
from . import a
from . import b
W a.py
import package
def func():
package.b.some_object()
W b.py
import package
def func():
package.a.some_object()
Więc to są Twoje opcje (i wszystkie są do bani IMO). Szczerze mówiąc, wydaje się to być rażącym błędem w maszynach importujących python, ale to tylko moje zdanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-17 01:08:49
Wykonujemy kombinację importu bezwzględnego i funkcji dla lepszego odczytu i krótszych ciągów dostępu.
- zaleta: krótsze ciągi dostępu w porównaniu z czystym importem absolutnym
- wada: trochę więcej kosztów z powodu dodatkowego wywołania funkcji
Main/sub/a.py
import main.sub.b
b_mod = lambda: main.sub.b
class A():
def __init__(self):
print('in class "A":', b_mod().B.__name__)
Main/sub/b.py
import main.sub.a
a_mod = lambda: main.sub.a
class B():
def __init__(self):
print('in class "B":', a_mod().A.__name__)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-08 13:30:40