2012-05-17 85 views
8

Tôi nhận ra câu hỏi khá giống với câu hỏi này, mặc dù không chính xác theo cách này.Có cách nào tốt để tạo một hàm tạo bản sao trong python không?

Tôi muốn có một đối số tùy chọn cho hàm tạo của lớp của tôi, nếu nó là một thể hiện của lớp của tôi, sẽ được sao chép. Ví dụ, một cái gì đó tương tự (tôi biết mã này không hoạt động!):

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 

Tôi biết có một số giải pháp thực tiễn cho việc này. Tôi có thể thiết lập mỗi thuộc tính của bản thân theo giá trị của thuộc tính tương ứng của foo, nhưng điều này sẽ thực sự gây phiền nhiễu bởi vì lớp của tôi có rất nhiều thuộc tính. Hoặc tôi chỉ đơn giản có thể sử dụng:

b = copy.deepcopy(a) 

... Nhưng tôi không muốn nếu điều đó là có thể. Tôi cũng hy vọng sẽ tránh ghi đè __new__.

Có thực sự không có cách nào phong nha ở tất cả trong python để tạo ra một nhà xây dựng bản sao?

+3

TẠI SAO không bạn muốn sử dụng b = copy.deepcopy (a)? Ý tôi là, nếu nó hoạt động, và không cần thêm bất kỳ dòng nào để viết hơn b = Foo (a) .... – DGH

+0

Vâng, tôi cho rằng ngón tay của tôi vẫn bị gạch chéo rằng một hàm tạo bản sao là khả thi. Và thẳng thắn, tại sao phải không? Nó không giống như nó là một yêu cầu thực sự bất thường. Người ta sẽ nghĩ rằng tất cả các ngôn ngữ hướng đối tượng sẽ có tính năng này. – carmenism

+1

Tại sao nó không phải là một tính năng? Bởi vì nó chỉ là đường cú pháp, một cách khác để nói chính xác điều tương tự. Miễn là chức năng tồn tại để tạo bản sao sâu chỉ với một dòng mã rất đơn giản, tại sao nó lại quan trọng nếu đó là "hàm tạo" hay không? – DGH

Trả lời

16

Tôi nghĩ đây là cách thức nhiệt tình nhất để thực hiện nó - một phương pháp sao chép nhà máy.

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 

Điều này khá phổ biến trong các loại cơ bản python (ví dụ: dict.copy). Nó không phải là một nhà xây dựng bản sao, nhưng tôi không nghĩ rằng đó là một khái niệm rất nhiệt đới!

+0

Đó là một ý tưởng khác mà tôi quên đề cập đến trong câu hỏi của mình. Tôi thích điều này hơn b = copy.deepcopy (a) ít nhất. Cảm ơn bạn! – carmenism

0

Đó là thể, trong đó bạn chỉ có thể lặp qua tất cả các thuộc tính trên đối tượng nguồn truyền cho __init__, và sau đó setattr() những người bạn quan tâm trên self. Nhưng nó không phải ở tất cả rõ ràng đây sẽ là một cách tốt để giải quyết một vấn đề. Không phải là rất Pythonic, và tất cả.

+0

Tôi tự hỏi về điều đó, nhưng nó thực sự không có vẻ rất Pythonic. Dù sao cũng cảm ơn bạn. – carmenism

0

Một cách hay để làm điều này là tạo một bản sao cấp cao nhất của không gian tên của cá thể.

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 

Nhưng hãy cẩn thận nếu giao lớp học của bạn với __slots__, bởi vì trong trường hợp đó __dict__ có thể vắng mặt và do đó bạn có thể cần phải dựa vào cơ chế thuộc tính nhận được trung lập hơn, chẳng hạn như getattr()

Các vấn đề liên quan