2016-07-25 8 views
1

Ich habe eine Klasse, die eine Instanz derselben Klasse als Initialisierung akzeptieren soll; In diesem Fall wird diese Instanz einfach zurückgegeben.Die beste Python-Methode, um den Initialisierungswert der Klasse bei derselben Klasse zurückzugeben

Der Grund ist, dass ich möchte, dass diese Klasse eine Unzahl von Initialisierungswerten akzeptiert, und dann kann der fortschreitende Code dies als ein Objekt mit bekannten Eigenschaften verwenden, unabhängig davon, wie es initialisiert wurde.

Ich habe gedacht, so etwas wie:

class c(object): 
    def __new__(cls, *args, **kwargs): 
    if isinstance(args[0], c): 
     return args[0] 
    else: 
     return super(c, cls).__new__(cls, *args, **kwargs) 

Das Problem ist, dass ich nicht __init__() will aufgerufen, wenn auf diese Weise initialisiert werden. Gibt es einen anderen Weg?

Danke!

+0

Warum wollen Sie nicht '__init __()' aufgerufen werden? Wäre es in Ordnung, wenn "__init __()" aufgerufen würde, aber nichts unternommen hätte? –

+0

'__init __()' sollte nur aufgerufen werden, wenn args [0] nicht von der Klasse ist – Pato

+0

Ja, das haben Sie bereits in Ihrer Frage angegeben. Aber ich frage Sie: Warum ist das wichtig? Wie wichtig ist es, dass Sie den Anruf vermeiden? Sie können den Aufruf leicht dazu veranlassen, nichts zu tun, wenn Sie mit einer Instanz initialisieren, oder etwas tun, wenn Sie mit anderen Werten initialisieren. –

Antwort

1

Sie möchten wahrscheinlich eine Fabrik verwenden (siehe zB question für Details oder Google). Oder benutzen Sie einfach eine Klassenmethode für das, was Sie wollen, zB:

class C(object): 
    @classmethod 
    def new(cls, *args, **kwargs): 
     if isinstance(args[0], cls): 
      return args[0] 
     else: 
      return cls(*args, **kwargs) 

obj = C.new() 
obj2 = C.new(obj) 
1

Sie können eine Metaklasse verwenden

class InstanceReturnMeta(type): # You should probably think of a better name 
    def __call__(cls, *args, **kwargs): 
     if args and isinstance(args[0], cls): 
      return args[0] 
     instance = cls.__new__(cls, *args, **kwargs) 
     instance.__init__(*args, **kwargs) 
     return instance 


class Test(object): 
    __metaclass__ = InstanceReturnMeta 
    def __init__(self, value): 
     self.value = value 

Lassen Sie uns es testen

In [3]: instance1 = Test(0) 
In [4]: instance2 = Test(instance1) 
In [5]: print id(instance1) == id(instance2) 
Out[5]: True 

Die IDs identisch sind, damit beide Variablen verweisen auf dieselbe Instanz.

P.S. Ich nehme an, Sie sind auf Python 2, da Ihre Klasse explizit von object erbt.

1

Der Standard Weg dies zu tun ist einfach nicht Ihre Initialisierung in __init__ zu tun. Tun Sie es in __new__.

Verwandte Themen