2010-01-26 32 views
7

Bất cứ ý tưởng nếu có một cách để làm cho đoạn mã sau để làm việcThay đổi lớp dụ bên trong một phương pháp dụ

class Test(object): 

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

    def changeme(self): 
     self = Test(3) 

t = Test(1) 
assert t.var == 1 
t.changeme() 
assert t.var == 3 

là một cái gì đó giống như an toàn sau đây để sử dụng cho các đối tượng phức tạp hơn (như mô hình django, để nóng hoán đổi mục nhập db mà cá thể đang đề cập đến)

class Test(object): 

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

    def changeme(self): 
     new_instance = Test(3) 
     self.__dict__ = new_instance.__dict__ 

t = Test(1) 
assert t.var == 1 
t.changeme() 
assert t.var == 3 
+2

Tại sao? Bạn rõ ràng muốn có một ví dụ mới, tại sao không chỉ tạo một trường hợp mới và ném cái này đi? Xin hãy giải thích cho chúng tôi. –

Trả lời

7

self = Test(3) đang ràng buộc lại tên địa phương self, không có tác động quan sát bên ngoài.

Gán self.__dict__ (trừ khi bạn đang nói về trường hợp với __slots__ hoặc từ các lớp học với metaclasses không tầm thường) thường là OK, và như vậy là self.__init__(3) để tái khởi tạo các ví dụ. Tuy nhiên tôi muốn có một phương pháp cụ thể self.restart(3)biết nó đang được gọi trên một trường hợp đã được khởi tạo và làm bất cứ điều gì cần thiết để phục vụ cho trường hợp cụ thể và bất thường đó.

+0

Mô hình metaclasses của Django là ... lộn xộn. Tôi sẽ không ngạc nhiên nếu cố gắng phân công lại 'self .__ dict__' đã thổi bay một cách ngoạn mục. –

+0

@Ignacio, với "metaclasses không tầm thường" trong trò chơi (hoặc '__slots__', v.v.), bạn có thể muốn sử dụng vòng lặp' getattr'/'setattr' thay thế. Lợi thế của việc viết phương thức 'restart' mà tôi ủng hộ là bạn cô lập ở đó việc tinh chỉnh (nếu có) cần thiết để hỗ trợ các trường hợp khác nhau, từ các đối tượng bình thường đến các đối tượng có metaclasses và vân vân. –

3

Không, và không.

Có nói rằng, bạn có thể thay đổi lớp, nhưng cũng không làm điều đó.

2

Mã cũ hoạt động, ngoại trừ nó sẽ không làm được gì nhiều, vì nó chỉ thay thế đối tượng có tên 'self' trong phạm vi của changeme(). Tên Python không bị khóa với giá trị, chúng luôn luôn liên quan đến phạm vi hoặc không gian tên của chúng.

Để làm những gì bạn muốn, bạn sẽ cần phải có quyền truy cập vào một tên bên ngoài lớp học, mà bạn có thể gán cho từ bên trong nó:

class Test: 
    def changeme(self): 
    global myclass 
    myclass = Test(3) 

myclass = Test(2) 
myclass.changeme() 
print myclass # 3 

này về cơ bản chỉ ghi đè tên 'myclass' để chỉ với phiên bản mới. Nó không "ghi đè lên" ví dụ đầu tiên như bạn nghĩ. Ví dụ cũ vẫn còn sống, và sẽ được thu thập rác thải trừ khi được tham chiếu ở nơi khác.

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