Ответ 1
Для этого вам нужно __new__()
. (И вам также нужно сделать его классом нового стиля, предполагая, что вы используете Python 2, путем подкласса object
.)
class ClassA(object):
def __new__(cls,theirnumber):
if theirnumber > 10:
# all big numbers should be ClassB objects:
return ClassB.ClassB(theirnumber)
else:
# numbers under 10 are ok in ClassA.
return super(ClassA, cls).__new__(cls, theirnumber)
__new__()
выполняется как часть процесса создания класса до __init__()
. В основном __new__()
- это то, что на самом деле создает новый экземпляр, а затем __init__()
вызывается для инициализации его свойств. Вот почему вы можете использовать __new__()
, но не __init__()
для изменения типа созданного объекта: как только __init__()
запускается, объект уже создан и слишком поздно, чтобы изменить его тип. (Ну... не совсем, но это попадает в очень загадочную черную магию Python.) См. документацию.
В этом случае, однако, я бы сказал, что функция factory более подходит, что-то вроде
def thingy(theirnumber):
if theirnumber > 10:
return ClassB.ClassB(theirnumber)
else:
return ClassA.ClassA(theirnumber)
Кстати, обратите внимание, что если вы сделаете то, что я сделал с __new__()
выше, если возвращается ClassB
, метод __init__()
экземпляра ClassB
не будет вызываться! Python только вызывает __init__()
, если объект, возвращаемый из __new__()
, является экземпляром класса, в котором содержится метод __new__()
(здесь ClassA
). Этот еще один аргумент в пользу функционального подхода factory.