2016-07-14 3 views
-1

Поэтому у меня есть следующий код декоратор Python класс декоратора, не может использовать конструктор

class Factory: 

    def __init__(self, cls): 
     self.cls = cls 

    def __instancecheck__(self, inst): 
     return isinstance(inst, self.cls) 

    def Produce(self): 
     return self.cls() 

и следующий код учащемуся

@Factory 
class Foo: 

    def __init__(self, arg): 
     self.arg = arg 

    def method(self): pass 

который прекрасно работает. Позволяет мне делать такие вещи, как

Foo.Produce().method()

Вместо

instance = Foo() 
instance.method() 

Но теперь я не могу использовать конструктор класса обычно

Foo(arg) 

дает исключение «объект Factory не отозваны. Мой вопрос заключается в следующем: как я могу сделать декоратор, который позволяет мне создавать экземпляр класса с использованием его конструктора, но также позволяет мне использовать функцию в декораторе?

Альтернативные способы я предпочел бы не использовать:

  1. Пропустить конструктор. Всегда используйте <Class>.Produce() (и использовать *args/**kwargs, чтобы сделать его абстрактным/многоразовым.
  2. Используйте сеттер во всех классах, и заставить их вернуться self так что они могут быть прикованы.
  3. сделать класс, содержащим метод производит и расширить это . класс
+1

Вы могли бы реализовать '__call__' на' Factory'. – jonrsharpe

+2

Я не уверен, что понимаю преимущества метода «Produce». «Вещь», которую вы показываете, что она позволяет вам сделать, эквивалентна 'Foo(). Method()' для недееспособного класса. Вам не нужно привязывать экземпляр к переменной, если вы не хотите (хотя обычно это делаете). – Blckknght

+0

@Blckknght Теперь я чувствую себя довольно глупо. Был очень воспитательный. Java, C#, PHP все не позволяют. Поэтому я предположил, что для питона все одинаково. – Neo

ответ

2

исключение говорит вам все, что вам нужно знать, просто добавьте __call__ метод:

class Factory: 
    # ... 

    def __call__(self, *args, **kwargs): 
     return self.cls(*args, **kwargs) 
+0

Вы, сэр, только что решили мою проблему. Большое спасибо. – Neo

-1

Если все, что вам нужно сделать, это добавить Produce функция класса, вы можете переписать декоратор так:

def Factory(cls): 
    def Produce(): 
     return cls() 
    cls.Produce= Produce # add the function to the class 
    return cls 
Смежные вопросы