2013-06-29 3 views
8

Скажем, у меня есть два класса А и В:Python: доступ к атрибутам и методам одного класса в другой

Class A: 
    # A's attributes and methods here 

Class B: 
    # B's attributes and methods here 

Теперь я могу оценить свойства элементов а в объект класса B следующим образом:

a_obj = A() 
b_obj = B(a_obj) 

Мне нужен двухсторонний доступ. Как получить доступ к свойствам A в свойствах B и B в A?

+0

Вы хотите сказать, что хотите получить доступ к членам a_obj в b_obj? Или вы просто хотите, чтобы классы имели свойства с одинаковыми именами? – Ishpeck

+0

Я хочу получить доступ к свойствам каждого объекта из другого (взаимный доступ), и ответ Марджина позволяет мне это сделать :) – oat

ответ

10

Вам нужно создать указатели так или иначе:

class A(object): 
    parent = None 


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

Теперь A может относиться к self.parent (при условии, что это не None), и B может относиться к self.child. Если вы попытаетесь сделать экземпляр A дочерним числом более одного B, победит последний «родитель».

+1

Не могли бы вы подробнее рассказать о том, как вы создаете объекты из двух. – oat

+1

Я использовал * ваш * пример в конце, фактически. –

5

Почему бы просто не планировать свои объекты так, чтобы об этом можно было позаботиться с наследованием.

class A(object): 
    # stuff 

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

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

В данном случае строгания вперед, вы могли бы просто использовать C для универсалом объекта и A с B как более специализированными/голыми родителями.

+1

очень проницательный, но зашли слишком далеко в мою текущую программу, чтобы позволить себе реструктурировать класс. Урок, извлеченный для будущего :) – oat

+3

Это очень простой пример наследования, я бы призвал вас к черту из этой темы :). Наследование похоже на основную особенность языков ООП, таких как Python. Удачи @QuakiGabbar! –

3

Этот метод будет очень полезен, так как вы можете использовать объекты обоих классов взаимозаменяемо. В этом есть серьезная проблема, я объясню это в конце.

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 + "`") 

Объяснение:

Согласно this page, __getattr__ и __setattr__ будут вызываться на объектах питона только тогда, когда запрашиваемый атрибут не найден в пространстве конкретного объекта. Поэтому в конструкторе мы устанавливаем связь между обоими классами. И тогда, когда вызывается __getattr__ или __setattr__, мы ссылаемся на другой объект, используя метод getattr. (getattr, setattr) Мы используем __dict__ для назначения значений в конструкторе, чтобы мы не вызывали __setattr__ или __getattr__.

Примеры Запускаются:

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 

Теперь серьезная проблема:

Если попытаться получить доступ к атрибуту, который не является там в обеих этих объектах, мы будем в конечном итоге в бесконечном рекурсии. Допустим, я хочу получить доступ к 'C' из 'a'. Поскольку C не находится в a, он будет называть __getattr__, и он будет ссылаться на объект b. Поскольку объект b не имеет C, он вызывает __getattr__, который будет ссылаться на объект a. Таким образом, мы оказываемся в бесконечной рекурсии. Таким образом, этот подход работает отлично, когда вы не получаете доступ к чему-либо неизвестному для обоих объектов.

+0

Зачем дублировать объявление одинаковых методов как для 'A', так и' B', I.e. геттер и сеттер? Я чувствую, что эта техника не обладает всеми преимуществами полиморфизма, еще +1 для усилий. –

+0

@MorganWilde OP не мог позволить себе полиморфизм. Он упомянул об этом в одном из комментариев :(Спасибо за upvote :) – thefourtheye

Смежные вопросы