2009-06-16 47 views
7

Trong lớp B bên dưới, tôi muốn hàm __set__ trong lớp A được gọi bất cứ khi nào bạn gán giá trị cho B().a. Thay vào đó, hãy đặt giá trị thành B().a ghi đè B().a bằng giá trị. Lớp C gán cho C().a hoạt động chính xác, nhưng tôi muốn có một phiên bản A riêng biệt cho mỗi lớp người dùng, tức là tôi không muốn thay đổi 'a' trong một phiên bản C() để thay đổi 'a' trong tất cả các phiên bản khác. Tôi đã viết một vài bài kiểm tra để giúp minh họa vấn đề. Bạn có thể giúp tôi xác định một lớp học sẽ vượt qua cả test1 và test2?Tại sao việc khai báo một lớp mô tả trong hàm __init__ phá vỡ chức năng mô tả?

class A(object): 
    def __set__(self, instance, value): 
     print "__set__ called: ", value 

class B(object): 
    def __init__(self): 
     self.a = A() 

class C(object): 
    a = A() 

def test1(class_in): 
    o = class_in() 
    o.a = "test" 
    if isinstance(o.a, A): 
     print "pass" 
    else: 
     print "fail" 

def test2(class_in): 
    o1, o2 = class_in(), class_in() 
    if o1.a is o2.a: 
     print "fail" 
    else: 
     print "pass" 

Trả lời

4

Theo đó đến documentation:

Các phương pháp sau chỉ áp dụng khi một thể hiện của lớp chứa phương pháp (một cái gọi là mô tả lớp) xuất hiện trong lớp học từ điển của một lớp học kiểu mới, được gọi là lớp chủ sở hữu. Trong ví dụ bên dưới, “thuộc tính” đề cập đến thuộc tính có tên là chìa khóa của thuộc tính trong lớp chủ sở hữu '__dict__. Chỉ có thể thực hiện mô tả là các lớp kiểu mới.

Vì vậy, bạn không thể có mô tả về các phiên bản.

Tuy nhiên, vì bộ mô tả nhận được tham chiếu đến cá thể đang được sử dụng để truy cập nó, chỉ cần sử dụng nó làm khóa để lưu trữ trạng thái và bạn có thể có hành vi khác nhau tùy thuộc vào cá thể.

+0

OK, tôi có thể sống với điều đó – user83753

+0

Suy nghĩ thứ hai, có thể tôi không thể sống với điều đó. Trong ứng dụng của tôi, tôi muốn đặt các hàm thành viên trong A cũng phụ thuộc vào trạng thái của lớp chủ sở hữu. Ví dụ: Chủ sở hữu (thông tin tiểu bang) Chủ sở hữu.a = dữ liệu Chủ sở hữu.a.foo() Làm cách nào để nhận thông tin trạng thái từ Chủ sở hữu? – user83753

+0

@unknown (google): oh, để bạn lưu trữ dữ liệu trên chính cá thể đó. Vì vậy, bạn có thể lấy nó từ các phương pháp. – nosklo

0

Đây là một lớp học có thể vượt qua các bài kiểm tra ban đầu, nhưng đừng cố gắng sử dụng nó trong hầu hết các trường hợp. nó thất bại trong việc kiểm tra isinstance trên chính nó!

class E(object): 
    def __new__(cls, state): 
     class E(object): 
      a = A(state) 
      def __init__(self, state): 
       self.state = state 
     return E(state) 

#>>> isinstance(E(1), E) 
#False 
+0

đó là chức năng của nhà máy lớp học, được cải trang thành lớp – nosklo

+0

Có, và tự hào về nó. – user83753

0

Tôi bị cắn bởi một vấn đề tương tự ở chỗ tôi muốn lớp đối tượng có thuộc tính được điều chỉnh bởi bộ mô tả. Khi tôi đã làm điều này, tôi nhận thấy rằng các thuộc tính đã được ghi đè trong tất cả các đối tượng như vậy mà họ không phải là cá nhân.

tôi nêu ra một câu hỏi SO và câu trả lời kết quả là đây: class attribute changing value for no reason

Một liên kết tài liệu tốt thảo luận mô tả là ở đây: http://martyalchin.com/2007/nov/24/python-descriptors-part-2-of-2/

Tên mô tả ví dụ từ các liên kết nói trên là dưới đây:

class Numberise(object): 
    def __init__(self, name): 
     self.name = name 

    def __get__(self, instance, owner): 
     if self.name not in instance.__dict__: 
      raise (AttributeError, self.name) 
     return '%o'%(instance.__dict__[self.name]) 

    def __set__(self, instance, value): 
     print ('setting value to: %d'%value) 
     instance.__dict__[self.name] = value 
Các vấn đề liên quan