Python: получение значений базового класса из производного класса - PullRequest
9 голосов
/ 08 февраля 2011

Надеюсь, это достаточно ясно:

class myParent():
    def __init__( self ):
        self.parentNumber = 5

class Child( myParent ):
    def __init__( self ):
        self.childNumber = 4

    def multiplyNumbers( self ):
        print myParent.parentNumber * self.childNumber

p = Child()
p.multiplyNumbers()

Я хочу установить parentNumber индивидуально, а затем достичь этого числа через дочерний класс, и в этом случае использовать его для некоторого умножения.

Я новичок в области ООП, поэтому приветствуются любые общие указания по наследованию!

Подробнее: Я разрабатываю решение для управления проектами для проектов на основе vfx и играю с классами и наследованием, чтобы понять, как они могут помочь мне больше всего.

Прямо сейчас у меня есть высший класс Project и производный класс Shot. Выстрел имеет переменную self.length с длиной конкретного выстрела. Он также получил метод getLengthInSeconds (), который использует self.length вместе с Project.fps для определения длины в секундах. Project имеет метод setFps (), в котором fps устанавливается после создания экземпляра класса.

Я вроде как привык к переменным с префиксом self. и не много экспериментировал с классами, использующими более «глобальные» переменные без self. , Если я сделаю все глобально, а не себя, я могу без проблем использовать Project.fps, но в моем шейном волосе появляется предупреждение о «плохой практике программирования». Возможно, есть лучший, более аккуратный способ?

Edit:

После некоторого чтения super () кажется довольно опасным, и я думаю, что это немного больше, чем мне нужно. У меня в основном классы с одним наследованием, и я даже не уверен, как использовать иерархии алмазов. Есть ли более безопасный способ доступа к переменным и методам суперкласса, который не включает super ()?

Edit:

Хорошо, посмотрите, имеет ли это смысл или я все об этом думаю неправильно.

Я смотрю на классы и наследование как группы и детей. Ребенок знает, что это родитель и все его ценности. Ребенок другому родителю знает, что родители ценят. То, что я пытаюсь сделать, это сделать все снимки частью проекта. И сейчас я создаю экземпляры Shot () из класса Project (), добавляя экземпляры в список снимков, который затем поддерживается в экземпляре Project ().

т.е.

class myParent( object ):
    def __init__( self ):
        self.parent_id = ''
        self.children = []

    def createChild( self, name ):
        self.children.append( myChild( name ) )

    def getChildren( self ):
        return self.children

    def setParentId( self, id ):
        self.parentId = id

class myChild( myParent ):
    def __init__( self, id ):
        super(myChild, self).__init__()
        self.id = id

    def getParentId( self ):
        return self.parent_id

p = myParent()
p.setParentId( 'parent01' )
p.createChild( 'child01' )
print p.getChildren()[0].getParentId()

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

Ответы [ 2 ]

6 голосов
/ 08 февраля 2011

Вам просто нужно указать Child, чтобы запустить инициализацию с myParent. После этого текущий экземпляр (self) имеет все атрибуты экземпляра, которые будет иметь экземпляр myParent ( "это" ), поэтому вы можете использовать self.parentNumber , Вы делаете это, помещая super(Child, self).__init__() в Child.__init__ (в идеале, в самой первой строке) - myParent.__init__(self) будет работать, но это может быть неправильно (тонким способом) при изменении базового класса или в случае множественного наследования. Вы можете сбросить все аргументы до super, если вы используете Python 3.

Также обратите внимание, что

class C(object):
    x = ...

очень отличается от

class C(object):
    def __init__(self):
        self.x = ...

Первый создает переменную класса, которая используется всеми экземплярами C. Последние создают переменную экземпляра, каждый экземпляр C имеет свою собственную. (Аналогично, глобальные переменные не привязаны к экземплярам - но я предполагаю, что вы говорили об этом выше?)

5 голосов
/ 09 февраля 2011
class myParent( object ):
    def __init__( self ):
        self.parentNumber = 5

class Child( myParent ):
    def __init__( self ):
        myParent.__init__( self )
        self.childNumber = 4

    def multiplyNumbers( self ):
        print self.parentNumber * self.childNumber

p = Child()
p.multiplyNumbers()

Обычно вы можете прекрасно обходиться без super, если у вас нет множественного наследования или других случаев с границами, хотя если базовый класс изменится, вам нужно помнить, чтобы изменить имя родительского класса с init (и любой другой метод, который явно ссылается на myParent).

Если __init__ вашего родителя принимает параметры, вам нужно передать их от __init__.

* 1010 вашего ребенка.*

Если вам не нравится повторение customParam во всех дочерних классах, есть альтернативный шаблон OO, называемый двухфазным построением, который работает следующим образом:

class myParent( object ):
    def customInit( self, customParam ):
        self.parentNumber = 5
        self.customParam = customParam

class Child( myParent ):
    def __init__( self, customParam ):
        self.childNumber = 4

p = Child()
p.customInit(10)
p.multiplyNumbers()

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

ОБНОВЛЕНИЕ (чтобы ответить на обновленный вопрос):

Вы, кажется, смешиваете две несвязанные концепции рАреантство здесь.Наследование связано с иерархией типов, и вы, похоже, следуете иерархии владения (is-a вместо has-a).

Я бы структурировал ваш обновленный код следующим образом:

class myParent( object ):
    def __init__( self, parentId ):
        self.id = parentId
        self.children = []

    def createChild( self, name ):
        self.children.append( myChild( name, self ) )

    def getChildren( self ):
        return self.children

class myChild( object ):
    def __init__( self, childId, parent ):
        self.id = childId
        self.parent = parent

    def getParentId( self ):
        return self.parent.id

p = myParent( 'parent01' )
p.createChild( 'child01' )
print p.getChildren()[0].getParentId()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...