Mam taką sytuację ...
class Outer(object):
def some_method(self):
# do something
class Inner(object):
def __init__(self):
self.Outer.some_method() # <-- this is the line in question
Jak mogę uzyskać dostęp do Outer
metody Inner
klasy z poziomu klasy?
python
scope
nested
inner-classes
T. Stone
źródło
źródło
self.<original_parent_name>
i dostać oryginalny klasę, a nie nową klasę, że są one z podklasy . Mam nadzieję, że ludzie, którzy to czytają, mogą sobie wyobrazić ten trudny scenariusz i dostrzec sens takich pytań.Odpowiedzi:
Metody klasy zagnieżdżonej nie mogą uzyskać bezpośredniego dostępu do atrybutów instancji klasy zewnętrznej.
Należy zauważyć, że niekoniecznie jest tak, że instancja klasy zewnętrznej istnieje, nawet jeśli utworzono instancję klasy wewnętrznej.
W rzeczywistości często odradza się używanie klas zagnieżdżonych, ponieważ zagnieżdżenie nie implikuje żadnego szczególnego związku między klasami wewnętrzną i zewnętrzną.
źródło
Próbujesz uzyskać dostęp do instancji klasy Outer z instancji klasy wewnętrznej. Po prostu użyj metody fabrycznej, aby zbudować instancję Inner i przekazać do niej instancję Outer.
źródło
może jestem szalony, ale wydaje się to rzeczywiście bardzo łatwe - chodzi o to, aby uczynić swoją wewnętrzną klasę metodą klasy zewnętrznej ...
Poza tym ... „siebie” jest używane tylko w konwencji, więc możesz to zrobić:
Można by się sprzeciwić, że nie możesz wtedy stworzyć tej klasy wewnętrznej spoza klasy zewnętrznej ... ale to nieprawda:
wtedy gdzieś mile stąd:
nawet wypchnij trochę łódź i rozszerz tę klasę wewnętrzną (uwaga: aby super () działało, musisz zmienić sygnaturę klasy mooble na "class mooble (object)"
później
mrh1997 podniósł interesującą kwestię dotyczącą rzadkiego dziedziczenia klas wewnętrznych dostarczanych przy użyciu tej techniki. Ale wydaje się, że rozwiązanie jest dość proste:
źródło
Czy masz zamiar używać dziedziczenia zamiast zagnieżdżania klas w ten sposób? To, co robisz, nie ma sensu w Pythonie.
Możesz uzyskać dostęp do
Outer
metody some_method, odwołując sięOuter.some_method
do metod klasy wewnętrznej, ale nie będzie ona działać tak, jak się spodziewasz. Na przykład, jeśli spróbujesz tego:... otrzymasz TypeError podczas inicjalizacji
Inner
obiektu, ponieważOuter.some_method
oczekuje , żeOuter
jako pierwszy argument otrzyma instancję. (W powyższym przykładzie zasadniczo próbujesz wywołaćsome_method
jako metodę klasyOuter
.)źródło
Możesz łatwo uzyskać dostęp do zewnętrznej klasy za pomocą metaklasy: po utworzeniu klasy zewnętrznej sprawdź jej atrybut dict dla dowolnej klasy (lub zastosuj dowolną logikę, której potrzebujesz - mój to tylko trywialny przykład) i ustaw odpowiednie wartości:
Korzystając z tego podejścia, możesz łatwo wiązać i odnosić się do dwóch klas między sobą.
źródło
Stworzyłem kod w Pythonie, aby używać zewnętrznej klasy z jej klasy wewnętrznej , w oparciu o dobry pomysł z innej odpowiedzi na to pytanie. Myślę, że jest krótki, prosty i łatwy do zrozumienia.
Główny kod „do produkcji” (bez komentarzy itp.). Pamiętaj, aby zastąpić wszystkie wartości w nawiasach ostrych (np.
<x>
) Żądaną wartością.Wyjaśnienie, jak działa ta metoda (podstawowe kroki):
Utwórz funkcję o nazwie,
_subclass_container
która będzie działać jako opakowanie, aby uzyskać dostęp do zmiennejself
, odwołanie do klasy wyższego poziomu (z kodu działającego wewnątrz funkcji).Utwórz zmienną o nazwie,
_parent_class
która jest odniesieniem do zmiennejself
tej funkcji, do której podklasy_subclass_container
mają dostęp (pozwala to uniknąć konfliktów nazw z innymiself
zmiennymi w podklasach).Zwróć podklasy / podklasy jako słownik / listę, aby kod wywołujący
_subclass_container
funkcję mógł uzyskać dostęp do podklas wewnątrz.W
__init__
funkcji wewnątrz klasy wyższego poziomu (lub gdziekolwiek jest to potrzebne), odbierz zwrócone podklasy z funkcji_subclass_container
do zmiennejsubclasses
.Przypisz podklasy przechowywane w
subclasses
zmiennej do atrybutów klasy wyższego poziomu.Kilka wskazówek ułatwiających scenariusze:
Ułatwienie kopiowania kodu przypisującego podklasy do klasy wyższego poziomu i używanie go w klasach pochodnych klasy wyższego poziomu, które mają
__init__
funkcja została zmieniona:Wstaw przed linią 12 w głównym kodzie:
Następnie wstaw do tej funkcji wiersze 5-6 (głównego kodu) i zamień wiersze 4-7 na następujący kod:
Umożliwienie przypisywania podklas do klasy wyższego poziomu, gdy istnieje wiele / nieznanych ilości podklas.
Zastąp wiersz 6 następującym kodem:
Przykładowy scenariusz, w którym to rozwiązanie byłoby przydatne i gdzie nie można uzyskać nazwy klasy wyższego poziomu:
Tworzona jest klasa o nazwie „a” (
class a:
). Ma podklasy, które muszą mieć do niego dostęp (rodzic). Jedna podklasa nosi nazwę „x1”. W tej podklasie koda.run_func()
jest uruchamiany.Następnie tworzona jest inna klasa o nazwie „b”, pochodząca z klasy „a” (
class b(a):
). Następnie zostaje uruchomiony jakiś kodb.x1()
(wywołanie funkcji podrzędnej „x1” z b, pochodnej podklasy). Ta funkcja działaa.run_func()
, wywołując funkcję „run_func” klasy „a”, a nie funkcję „run_func” jej rodzica, „b” (tak jak powinna), ponieważ funkcja, która została zdefiniowana w klasie „a” ma odwoływać się do funkcji klasy „a”, ponieważ była ona jej rodzicem.Spowodowałoby to problemy (np. Gdyby funkcja
a.run_func
została usunięta), a jedynym rozwiązaniem bez przepisywania kodu w klasiea.x1
byłoby ponowne zdefiniowanie podklasyx1
ze zaktualizowanym kodem dla wszystkich klas pochodzących z klasy „a”, co oczywiście byłoby trudne i niewarte to.źródło
Znalazłem to .
Dostosowano do twojego pytania:
Jestem pewien, że możesz jakoś napisać dekoratora do tego czy czegoś
powiązane: Jaki jest cel klas wewnętrznych Pythona?
źródło
Inna możliwość:
źródło
Rozwijając przekonujące myślenie @ tsnorri, że metoda zewnętrzna może być metodą statyczną :
Teraz dana linia powinna działać, zanim zostanie faktycznie wywołana.
Ostatni wiersz w powyższym kodzie podaje klasie Inner statyczną metodę będącą klonem statycznej metody Outer.
Wykorzystuje to dwie funkcje Pythona: funkcje są obiektami , a zakres jest tekstowy .
... lub aktualna klasa w naszym przypadku. Zatem obiekty „lokalne” w stosunku do definicji klasy Outer (
Inner
isome_static_method
) mogą być odwoływane bezpośrednio w tej definicji.źródło
Kilka lat spóźniłem się na imprezę ... ale aby rozwinąć
@mike rodent
wspaniałą odpowiedź, poniżej podałem własny przykład, który pokazuje, jak elastyczne jest jego rozwiązanie i dlaczego powinno (lub powinno być ) zaakceptowane odpowiedź.Python 3.7.0
Wynik:
Ponownie, wspaniała odpowiedź, rekwizyty dla ciebie mikrofon!
źródło
To jest zbyt proste:
Wejście:
Wynik
klasa A func1
klasa B func1
źródło
func1
. I, równie zabawne, tworzyszA
wewnątrz konstruktora programuB
, który absolutnie NIE jest zewnętrznymA
obiektem klasy tego konkretnegoB
.