2010-03-18 5 views
2

У меня есть метод __new__ следующим образом:Python: переопределить __init__ арг в __new__

class MyClass(object): 
    def __new__(cls, *args): 
     new_args = [] 
     args.sort() 
     prev = args.pop(0) 
     while args: 
     next = args.pop(0) 
     if prev.compare(next): 
      prev = prev.combine(next) 
     else: 
      new_args.append(prev) 
      prev = next 
     if some_check(prev): 
      return SomeOtherClass() 
     new_args.append(prev) 
     return super(MyClass, cls).__new__(cls, new_args) 

    def __init__(self, *args): 
     ... 

Однако это не удается с предупреждением устаревания:

DeprecationWarning: object.__new__() takes no parameters 

SomeOtherClass может дополнительно получить создан как арг являются обработаны, поэтому они обрабатываются в __new__, а не в __init__

Каков наилучший способ пройти new_args до __init__?

В противном случае мне придется дублировать обработку аргументов в __init__ (без some_check)

ответ

5

Решение, которое я пошел с в конце концов должен был изменить вновь созданный объект в __new__ и удалить метод __init__ вообще:

def __new__(cls, *args): 
    ... # as above 
    new_self = super(MyClass, cls).__new__(cls) 
    new_self.args = new_args 
    return new_self 

#def __init__(self, *args): 
# self.args = args 
1

Поскольку вы даже не обязательно создавать объект MyClass, почему бы не просто поставить новый в отдельную функцию, которая возвращает new(*args) a MyClass или SomeOtherClass объект по мере необходимости?

Это будет немного более аккуратным, так как вы знаете, что везде, где вы положили MyClass(), вы возвращаете объект MyClass, а не потенциально SomeOtherClass, который может быть немного запутанным.

+0

В моем случае это дизайн, как MyClass и SomeOtherClass кооперативные типы, и могут обрабатываться взаимозаменяемо (общий интерфейс). – EoghanM

2

Редактировать: Придумал лучшее решение - следующее поведение не было достаточно стабильным.


Я решил свой собственный вопрос, спотыкаясь на какой-то неожиданно простое поведение:

return cls(*new_args) 

вместо

return super(MyClass, cls).__new__(cls, *new_args) 

Это не входит в бесконечную рекурсию, как я ожидается, пока new_args не совпадает с исходными аргументами, указанными в __new__.

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