2013-06-29 18 views
8

Powiedzmy mam dwie klasy A i B:Python: dostęp do atrybutów i metod jednej klasy w innym

Class A: 
    # A's attributes and methods here 

Class B: 
    # B's attributes and methods here 

Teraz mogę ocenić cech a w obiekcie klasy B, co następuje:

a_obj = A() 
b_obj = B(a_obj) 

Potrzebuję dostępu dwukierunkowego. Jak uzyskać dostęp do właściwości A we właściwościach B i B w A?

+0

Czy masz na myśli, że chcesz uzyskać dostęp do członków a_obj w b_obj? A może chcesz, aby klasy miały właściwości o tych samych nazwach? – Ishpeck

+0

Chcę uzyskać dostęp do właściwości każdego obiektu z drugiego (wzajemny dostęp), a odpowiedź Martjina pozwala mi to zrobić :) – oat

Odpowiedz

10

Musisz utworzyć wskaźniki w obu kierunkach:

class A(object): 
    parent = None 


class B(object): 
    def __init__(self, child): 
     self.child = child 
     child.parent = self 

Teraz A może odnosić się do self.parent (pod warunkiem, że nie jest None) i B może odnosić się do self.child. Jeśli spróbujesz utworzyć instancję A dziecka z więcej niż jednego B, ostatni "rodzic" wygrywa.

+1

Czy mógłbyś bardziej szczegółowo wyjaśnić, w jaki sposób tworzysz obiekty z dwóch? – oat

+1

W rzeczywistości użyłem * twojego * przykładu na końcu. –

5

Po prostu nie planuj swoich obiektów w taki sposób, w jaki można to zrobić z dziedziczeniem.

class A(object): 
    # stuff 

class B(A): 
    # has A methods/properties 

class C(B): 
    # has A and B methods/properties 

W tym przypadku przez struganie z wyprzedzeniem, można po prostu użyć C dla obiektu, różne branże i A z B bardziej wyspecjalizowanych/gołych rodziców.

+1

bardzo wnikliwe .. ale przeszedłem za daleko w moim obecnym programie, aby pozwolić sobie na restrukturyzację klasy. Lekcja nauczyła się na przyszłość :) – oat

+3

To jest bardzo prosty przykład dziedziczenia, zachęcam do Google'a do diabła z tego tematu :). Dziedziczenie jest jak główna cecha języków OOP, takich jak Python. Powodzenia @QuakiGabbar! –

3

Ta metoda będzie bardzo przydatna, ponieważ można używać obiektów obu klas zamiennie. Jest z tym poważny problem, wyjaśnię to na końcu.

class A: 
    def MethodA(self): 
     return "Inside MethodA" 

    def __init__ (self, Friend=None): 
     self.__dict__['a'] = "I am a" 
     self.__dict__['Friend'] = Friend 
     if Friend is not None: self.__dict__['Friend'].__dict__['Friend'] = self 

    def __getattr__(self, name): 
     if self.Friend is not None: return getattr(self.Friend, name) 
     raise AttributeError ("Unknown Attribute `" + name + "`") 

    def __setattr__(self, name, value): 
     if self.Friend is not None: setattr(self.Friend, name, value) 
     raise AttributeError ("Unknown Attribute `" + name + "`") 

class B: 
    def MethodB(self): 
     return "Inside MethodB" 

    def __init__ (self, Friend=None): 
     self.__dict__['b'] = "I am b" 
     self.__dict__['Friend'] = Friend 
     if Friend is not None: self.__dict__['Friend'].__dict__['Friend'] = self 

    def __getattr__(self, name): 
     if self.Friend is not None: return getattr(self.Friend, name) 
     raise AttributeError ("Unknown Attribute `" + name + "`") 

    def __setattr__(self, name, value): 
     if self.Friend is not None: setattr(self.Friend, name, value) 
     raise AttributeError ("Unknown Attribute `" + name + "`") 

Objaśnienie:

Zgodnie this page, __getattr__ i __setattr__ zostanie wywołana na obiekty Pythona tylko wtedy, gdy wnioskowana atrybut nie zostanie znaleziony w przestrzeni danego obiektu za. Tak więc w konstruktorze nawiązujemy relację między obiema klasami. Następnie, gdy wywoływane jest __getattr__ lub __setattr__, odsyłamy drugi obiekt za pomocą metody getattr. (getattr, setattr) Używamy __dict__, aby przypisać wartości w konstruktorze, abyśmy nie zadzwonili pod numer __setattr__ lub __getattr__.

Przykładowe zjazdowe:

b = B() 
# print b.a # Throws AttributeError, as A and B are not related yet 
a = A(b) 

print a.a 
print a.b 
print b.a  # Works fine here, as 'a' is not found b, returns A's a 
print b.b 

print a.MethodA() 
print a.MethodB() 
print b.MethodA() 
print b.MethodB() 

I am a 
I am b 
I am a 
I am b 
Inside MethodA 
Inside MethodB 
Inside MethodA 
Inside MethodB 

Teraz poważny problem:

Jeśli spróbujemy uzyskać dostęp do atrybutu, który nie jest tam w obu tych obiektów, ll skończyć się w nieskończony rekurencja. Powiedzmy, że chcę uzyskać dostęp do "C" z "a". Ponieważ C nie jest w a, będzie wywoływać __getattr__ i będzie odnosić się do obiektu b. Ponieważ obiekt b nie ma C, wywoła on __getattr__, który będzie odnosił się do obiektu a. Więc kończymy w nieskończonej rekursji. Tak więc to podejście działa dobrze, gdy nie uzyskujesz dostępu do niczego nieznanego obu obiektom.

+0

Dlaczego powielana jest deklaracja identycznych metod zarówno dla "A", jak i "B", tj. zdobywca i seter? Czuję, że w tej technice brakuje wszystkich korzyści z polimorfizmu, wciąż +1 za wysiłek. –

+0

@MorganWilde OP nie było stać na polimorfizm. Wspomniał o tym w jednym z komentarzy :(Dzięki za awans :) – thefourtheye

Powiązane problemy