Вы можете переопределить метод __new__
подкласса для создания экземпляров из альтернативного конструктора суперкласса, как показано ниже.
import math
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def from_polar(cls, radius, angle):
x = radius * math.cos(angle)
y = radius * math.sin(angle)
return cls(x, y)
class PointOnUnitCircle(Point):
def __new__(cls, angle):
point = Point.from_polar(1, angle)
point.__class__ = cls
return point
def __init__(self, angle):
pass
Обратите внимание, что в __new__
строку point = Point.from_polar(1, angle)
нельзя заменить на point = super().from_polar(1, angle)
, потому что, в то время как Point
отправляет себя в качестве первого аргумента альтернативного конструктора, super()
отправляет подкласс PointOnUnitCircle
альтернативному конструктору, который циклически вызывает __new__
подкласса, который его вызывает, и т. Д. пока не появится RecursionError
. Также обратите внимание, что даже если __init__
пуст в подклассе, без переопределения __init__
в подклассе, __init__
суперкласса будет автоматически вызываться сразу после __new__
, отменяя альтернативный конструктор.
В качестве альтернативы, некоторые конструкции объектов проще с композицией, чем с наследованием. Например, вы можете заменить указанный выше класс PointOnUnitCircle
, не переопределяя __new__
, следующим классом.
class UnitCircle:
def __init__(self, angle):
self.set_point(angle)
def set_point(self, angle):
self.point = Point.from_polar(1, angle)
person
Victor
schedule
14.01.2016
@classmethod
иself
?! Это действительно не сочетается. - person deceze♦   schedule 10.11.2015cls
, чтобы отличать его от экземпляраself
. Вы, конечно, можете получить доступ к методам класса черезself
, но в данном случае непонятно, зачем вам это нужно, поскольку метод класса устанавливает атрибут класса. - person jonrsharpe   schedule 10.11.2015self
в__init__
и ожидать, что это сработает. Если методы класса являются альтернативными конструкторами, почему бы просто не использоватьA10.from_half_a(5)
? - person jonrsharpe   schedule 10.11.2015@classmethod
не является инициализатором. [Отредактировано для удаления точек, которые уже были исправлены, когда я набирал это.] 4. Назначениеself
в инициализаторе ничего не даст, особенно если это последняя строка__init__
. ... Что, черт возьми, вы пытаетесь делать? В частности, как вы хотите, чтобы инициализированный дочерний экземпляр выглядел, и почему ни один из обычных способов сделать это не сработает для вас? - person Kevin J. Chase   schedule 10.11.2015@classmethods
в качестве альтернативных конструкторов. - person alex   schedule 10.11.2015cls
в@classmethod
состоит в том, чтобы вы могли вернуть экземпляр подкласса, поэтому нет необходимости вызывать его в методе__init__
подкласса. Он уже делает то, что вы хотите. - person Kevin J. Chase   schedule 10.11.2015__init__
, а не наоборот. Наследование уже делает то, что вы хотите, потому что вы использовалиcls(...)
, а неA(...)
в унаследованном методе. - person jonrsharpe   schedule 10.11.2015from_this
иfrom_that
, для создания альтернативных конструкторов. поэтому я пытаюсь просто использовать родительский альтернативный конструктор из дочернего класса. - person alex   schedule 10.11.2015cls(...)
изнутри метода класса, он вызывает__init__
(и / или__new__
) для любого классаcls
, создавая новый экземпляр. я пытаюсь просто использовать родительский альтернативный конструктор из дочернего класса, поэтому, снова, просто используйтеChildClass.inherited_class_method(...)
. См., Например, stackoverflow.com/q/1015592/3001761, stackoverflow.com/q/1216356/3001761, почему вы не можете назначитьself
. - person jonrsharpe   schedule 10.11.2015from_half_a
имеет ровно два параметра ---cls
иhalf_a
--- и ни один не является ссылкой на какой-то недавно созданный экземпляр, он не может быть инициализатором. - person Kevin J. Chase   schedule 10.11.2015__new__
. Не могли бы вы привести менее абстрактный пример того, чего вы на самом деле пытаетесь достичь? Обратите внимание, что вам нужно включать@username
при ответе на другие комментарии. - person jonrsharpe   schedule 10.11.2015A10()
должен нормально инициализировать класс,A10.from_half_a()
будет его альтернативным конструктором. Точно так же, как и для его родительского класса! ЗачемA10()
вдруг использовать альтернативный конструкторA
? - person deceze♦   schedule 10.11.2015SubclassOfA.__init__
. Кажется, это не тот ответ, который вам нужен, но на данный момент я понятия не имею, чего вы хотите. Вы намекнули, что происходит что-то гораздо более сложное, но не то, что это такое, и почему типичное использование__init__
или@classmethod
не сработает для вас. - person Kevin J. Chase   schedule 10.11.2015class A
был слишком простым, чтобы продемонстрировать вашу проблему. Как только вы показали нам, что вы на самом деле пытались сделать, это стал на удивление хорошим вопросом, на который менее чем через 10 минут был получен полезный (для вас и, вероятно, для других) ответ от @jonrsharpe. - person Kevin J. Chase   schedule 11.11.2015