2012-05-22 2 views
3

Я новичок в программировании и все еще изучаю свои канаты. Извините, если этот вопрос слишком элементарный.Правильный синтаксис для вложенных классов в Python?

Мне сложно прояснить мой вопрос, так что вот пример того, что я хочу выполнить: предположим, что a является экземпляром класса X и должен иметь атрибуты a1, a2, a3, b1, b2 , b3, c1, c2 и c3. Я хочу поставить a1 через a3, b1-b3 и c1-c3 в свои собственные классы A, B, C, вложенные под X для удобства использования. Каким будет правильный синтаксис?

class X: 
    def __init__ (self, name, A, B, C): 
     self.name = name 
     self.A = A 
     self.B = B 
     self.C = C 
    class A (X): 
     def _init_ (self, name, a1, a2, a3): 
      self.name = name 
      self.a1 = a1 
      self.a2 = a2 
      self.a3 = a3 
    class B (x): 
     def _init_ (self, name, b1, b2, b3): 
      self.name = name 
      self.b1 = a1 
      self.b2 = a2 
      self.b3 = a3 
    class C (X): 
     def _init_ (self, name, c1, c2, c3): 
      self.name = name 
      self.c1 = a1 
      self.c2 = a2 
      self.c3 = a3 

Поскольку это было построено исключительно на догадках, я 99,9% уверен, что это неправильно, но я не уверен, что я должен делать дальше, чтобы сделать это правильно. Я попытался найти ответы «вложенных классов», но ответы, которые я нашел, на самом деле не прояснили мою позицию.

Пожалуйста, объясните правильный синтаксис для вложенных классов в Python.

Благодарим за помощь и мои извинения за этот элементарный вопрос.

EDIT: В моих кодах были некоторые важные опечатки, которые я исправил только сейчас. Приношу свои извинения за любые неудобства.

+0

1. Не чувствуйте себя плохо. Если вы пытаетесь предоставить нам необходимую информацию, мы постараемся вам помочь. 2. Что вы подразумеваете под «вложенным классом»? В чем проблема, которую вы пытаетесь решить с помощью такой вложенности, и почему вы считаете, что такая вложенность является правильным решением для этой проблемы? – inspectorG4dget

ответ

1

Вы ищете наследование.

Кроме того, я заметил, что вам не хватает того, что python чувствителен к регистру. Это означает, что a и A НЕ тот же переменной

class X: 
    def __init__ (self, name, a, b, c): 
     self.name = name 
     self.a = a 

class A (X): 
    def _init_ (self, name, a1, a2, a3): 
     self.name = name 
     self.a1 = a1 
     self.a2 = a2 
     self.a3 = a3 

class B (A): 
    def _init_ (self, name, a1, a2, a3): 
     self.name = name 
     self.b1 = a1 
     self.b2 = a2 
     self.b3 = a3 

class C (A): 
    def _init_ (self, name, a1, a2, a3): 
     self.name = name 
     self.c1 = a1 
     self.c2 = a2 
     self.c3 = a3 

Надеется, что это помогает

+0

Приносим извинения за неудобства, но я небрежно пропустил какую-то важную информацию в своем коде в первый раз. Код выше - это то, что я пробовал - и не удалось. Еще раз, я был бы очень признателен, если бы вы могли помочь мне указать, что пошло не так. –

+0

Ничего из этого кода не будет работать. Нет никакого способа * подклассы * X будут добавлять свои атрибуты к * экземпляру * из 'X'. Нет супер-вызовов, поэтому наследование вообще не происходит. –

2

Вложенный класс просто одно определение которого существует в пределах другого. Они, как правило, не все, что полезно в Python. Однако можно делать то, что вы хотите, и выводить атрибуты одного класса из атрибутов многих; два основных метода: mixins/множественное наследование и Состав.

Mixin подход следующим образом:

class A(object): 
    def __init__(self, a=None, *args, **kwargs): 
     self.a = a 
     super(A, self).__init__(*args, **kwargs) 

class B(object): 
    def __init__(self, b=None, *args, **kwargs): 
     self.b = b 
     super(B, self).__init__(*args, **kwargs) 

class X(A, B): 
    def __init__(self, *args, **kwargs): 
     super(X, self).__init__(*args, **kwargs) 

x = X(a='foo', b='bar') 
print x.a, x.b 
  • Как X должен иметь атрибуты как A и B, мы это унаследовать от обоих: class X(A, B).

  • Each __init__ принимает *args, **kwargs в качестве параметров; наш super() вызов в X передает именованные параметры инициализаторам A и B, поэтому мы нуждаемся в нем, чтобы иметь возможность принимать (и затем игнорировать) параметры для других инициализаторов. То есть мы передаем a и b в A.__init__, но используем только a.

  • Чтение на super() необходимо для понимания наследования Python.

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

class A(object): 
    def __init__(self, a): 
     self.a = a 

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

class X(object): 
    def __init__(self, a, b): 
     self.A = A(a) 
     self.B = B(b) 

x = X('foo', 'bar') 
print x.A.a, x.B.b 

Вы можете увидеть это снимает необходимость в super() вызовов и для любой специальной обработки параметров на инициализаторе, что делает его намного яснее. Здесь мы берем два параметра, затем строим соответствующие классы внутри и присоединяем их к экземпляру X. Это делает атрибут поиск немного неудобно, но есть способы упрощения, что:

class X(object): 
    # <etc> 
    @property 
    def a(self): 
     return self.A.a 

Это также можно переопределить __getattr__ и сделать некоторую динамическую Lookups вместо ручного кодирования каждого свойства.

class X(object): 
    # <etc> 
    def __getattr__(self, item): 
     for component in (getattr(self, c) for c in ['A', 'B']): 
      if hasattr(component, item): 
       return getattr(component, item) 

Другой вариант, чтобы передать составленные экземпляры в себя:

class X(object): 
    def __init__(self, A, B): 
     self.A = A 
     self.B = B 

x = X(A('foo'), B('bar')) 
print x.A.a, x.B.b 

Это устраняет любую потребность в X ничего знать о A и B другой, чем их интерфейс. Это упрощает инкапсуляцию: теперь вы можете вставлять A и B в свои собственные модули, если это подходит. Вы также можете использовать заводскую функцию для удобства:

def make_X(a, b): 
    return X(
     A(a), 
     B(b) 
    ) 
Смежные вопросы