2012-05-17 9 views
8

Mi sono reso conto che domande del tutto simili sono state fatte, anche se non esattamente in questo modo.C'è un modo decente di creare un costruttore di copia in python?

Mi piacerebbe avere un argomento facoltativo per il costruttore della mia classe che, se è un'istanza della mia classe, verrà copiato. Ad esempio, una cosa del genere (So che questo codice non funziona!):

class Foo(object): 
    def __init__(self, foo=None): 
     self.x = None 
     self.y = None 
     self.z = None 

     if foo is not None and isinstance(foo, Foo): 
      self = copy.deepcopy(foo) 

a = Foo() 
a.x = 1 
a.y = 2 
a.z = 3 

b = Foo(a) 
print b.x 
print b.y 
print b.z 

So che ci sono un paio di soluzioni pratiche per questo. Potrei impostare ogni attributo di sé in base al valore dell'attributo corrispondente di foo, ma ciò sarebbe davvero fastidioso perché la mia classe ha molti, molti attributi. O potrei semplicemente usare fare:

b = copy.deepcopy(a) 

... Ma preferirei non se è possibile. Spero anche di evitare di scavalcare lo __new__.

c'è davvero nessun modo decente a tutti in python per creare un costruttore di copia?

+3

perché non farlo vuoi usare b = copy.deepcopy (a)? Voglio dire, se funziona, e non ci vogliono più righe per scrivere di b = Foo (a) .... – DGH

+0

Beh, suppongo che le mie dita siano ancora incrociate che un costruttore di copie sia fattibile. E francamente, perché non lo è? Non è come se fosse una richiesta davvero insolita. Si potrebbe pensare che tutti i linguaggi orientati agli oggetti abbiano questa caratteristica. – carmenism

+1

Perché non è una funzione? Perché è solo zucchero sintattico, un modo diverso per dire esattamente la stessa cosa. Finché esiste la funzionalità per fare una copia profonda con una sola linea di codice molto semplice, perché è importante se si tratta di un "costruttore" o no? – DGH

risposta

16

penso che questo è il modo più divinatorio di farlo - un metodo di copia di fabbrica.

import copy 

class Foo(object): 
    def __init__(self): 
     self.x = None 
     self.y = None 
     self.z = None 
    def copy(self): 
     return copy.deepcopy(self) 

a = Foo() 
a.x = 1 
a.y = 2 
a.z = 3 

b = a.copy() 
print b.x 
print b.y 
print b.z 

Questo è abbastanza comune in pitone tipi di base (es dict.copy). Non è un costruttore di copie, ma non penso che sia un concetto molto pitone!

+0

Questa era un'altra idea che ho dimenticato di menzionare nella mia domanda. Mi piace più di b = copy.deepcopy (a) almeno. Grazie! – carmenism

0

E 'possibile , nel senso che si può semplicemente iterare su tutti gli attributi sull'oggetto di origine passato a __init__, e poi setattr() quelli che ti interessano su self. Ma non è affatto chiaro che questo sarebbe un buon modo per risolvere un problema. Non molto Pythoniano, e tutto.

+0

Anch'io mi sono chiesto, ma in effetti non sembra molto pitonico. Grazie comunque. – carmenism

0

Un buon modo per farlo è quello di fare una copia di alto livello di spazio dei nomi dell'istanza.

class Tst: 
    def __init__(self, somearg): 
     if isinstance(somearg, self.__class__): 
      self.__dict__ = somearg.__dict__.copy() 
     else: 
      self.var = somearg 
    def echo(self): 
     print(self.var) 

a = Tst(123) 
b = Tst(456) 
a.echo()  # gives 123 
b.echo()  # gives 456 
c = Tst(a) 
c.echo()  # gives 123 
c.var is a.var # gives False -> different objects 

Ma attenzione se le tue offerte classe con __slots__, perché in tal caso __dict__ potrebbe essere assente e quindi potrebbe essere necessario fare affidamento su meccanismi di attributo-sempre più neutri, come ad esempio getattr()

Problemi correlati