2015-11-11 13 views
6

Tôi đã hiểu cách thay thế các phương thức tại thời gian chạy bằng Python bằng cách xem các liên kết này. [Link1, Link2, & Link3].Phương pháp thay thế trong thời gian chạy không cập nhật Các thuộc tính riêng

Khi tôi thay thế phương thức "update_private_variable" của lớp A, nó sẽ được thay thế nhưng không cập nhật biến riêng tư.

import types 

class A: 
    def __init__(self): 
     self.__private_variable = None 
     self.public_variable = None 

    def update_private_variable(self): 
     self.__private_variable = "Updated in A" 

    def update_public_variable(self): 
     self.public_variable = "Updated in A" 

    def get_private_variable(self): 
     return self.__private_variable 

class B: 
    def __init__(self): 
     self.__private_variable = None 
     self.public_variable = None 

    def update_private_variable(self): 
     self.__private_variable = "Updated in B" 

    def update_public_variable(self): 
     self.public_variable = "Updated in B" 

Khi gọi phương thức mà không cần thay thế:

a_instance = A() 
a_instance.update_private_variable() 
print(a_instance.get_private_variable()) 
#prints "Updated in A" 

Khi gọi phương thức sau thay thế:

a_instance = A() 
a_instance.update_private_variable = types.MethodType(B.update_private_variable, a_instance) 
a_instance.update_private_variable() 
print(a_instance.get_private_variable()) 
#prints None 

Trong khi thay thế và gọi một phương thức mà cập nhật biến công cộng, hoạt động tốt

a_instance = A() 
a_instance.update_public_variable = types.MethodType(B.update_public_variable, a_instance) 
a_instance.update_public_variable() 
print(a_instance.public_variable) 
#prints 'Updated in B' 

Có cách nào khác để thay thế phương thức của một thể hiện trong thời gian chạy, để các thuộc tính riêng được cập nhật bằng cách gọi phương thức thay thế?

+0

Tôi gặp lỗi trên 'a_instance.update_private_variable()' sau khi rebinding 'update_private_variable'. 'TypeError: phương thức unbound update_private_variable() phải được gọi với đối tượng B làm đối số đầu tiên (có một cá thể A) thay vì' Cũng không có hệ thống công cộng/riêng tư thực tế nào. 'public_variable' và' __private_variable' đều có thể truy cập được với người dùng như nhau. – SuperBiasedMan

+3

Bạn có thể gặp sự cố với tên "mangling" *, được gọi bởi tên thuộc tính '__leading_double_underscore' - sử dụng' _leading_single_underscore' để biểu thị riêng theo quy ước và dự trữ đôi để tránh xung đột giữa các lớp con. – jonrsharpe

+0

@jonrsharpe: Tôi đã thử với '_leading_single_underscore', nó hoạt động bình thường. Nhưng theo yêu cầu của tôi, tôi không thể thay đổi _ "quy ước đặt tên" _ – user3262851

Trả lời

1

Ý tưởng đằng sau tên mangling là để bảo vệ các biến cấp cơ sở không bị làm phiền bởi các lớp con; nói cách khác, bạn không nên sử dụng nó nếu bạn nghĩ rằng các lớp con sẽ có một lý do chính đáng để sửa đổi những biến tương tự.

Có nói rằng, nếu bạn đã tốt xuống con đường đó và không thể (hoặc không muốn) để thay đổi nó bây giờ, bạn vẫn có thể nhận được bằng, nhưng nó sẽ xấu xí và giòn:

class B: 

    def update_private_variable(self): 
     self._A__private_variable = "Updated in B" 

Như bạn có thể thấy, bạn phải thêm tiền tố biến tên đọc sai với một _ và tên của lớp biến được đọc sai trong một số hậu quả:.

  • nếu bạn thay đổi tên của lớp, bạn phải thay đổi tên trong tất cả các tham chiếu đến nó
  • bạn không thể dễ dàng sử dụng cùng phương thức update_private_variable (vì bạn phải bằng cách nào đó chỉ ra lớp mục tiêu ... Tôi cho rằng bạn có thể vượt qua lớp đích vào phương pháp, nhưng điều đó thật tệ hơn)
Các vấn đề liên quan