2010-09-15 41 views
6

Tôi có một lớp được gọi là di động:Cách dễ dàng ghi đè các phương thức mặc định trong các lớp Python tùy chỉnh?

class Cell: 

    def __init__(self, value, color, size): 
     self._value = value 
     self._color = color 
     self._size = size 

    # and other methods... 

Cell._value sẽ lưu trữ một chuỗi, số nguyên, vv (bất cứ điều gì tôi đang sử dụng là đối tượng cho). Tôi muốn tất cả các phương pháp mặc định mà thông thường sẽ sử dụng "giá trị" của một đối tượng sử dụng <Cell object>._value vì vậy mà tôi có thể làm:

>>> c1 = Cell(7, "blue", (5,10)) 
>>> c2 = Cell(8, "red", (10, 12)) 
>>> print c1 + c2 
15 

>>> c3 = Cell(["ab", "cd"], "yellow", (50, 50)) 
>>> print len(c3), c3 
2 ['ab', 'cd'] 

# etc. 

tôi có thể ghi đè lên tất cả các phương pháp mặc định:

class Cell: 

    def __init__(self, value, color, size): 
     # ... 

    def __repr__(self): 
     return repr(self._value) 

    def __str__(self): 
     return str(self._value) 

    def __getitem__(self, key): 
     return self._value[key] 

    def __len__(self): 
     return len(self._value) 

    # etc. 

... nhưng có cách nào dễ hơn không?

+1

tại sao một số nguyên, 'self._value', có khả năng được chỉ mục bằng khóa không? Và bạn đã bao giờ thử lấy chiều dài của một số nguyên chưa? Ngoài ra, điều này có lẽ không nên là cocmmunity wiki: không ai có được điểm để trả lời theo cách đó và chúng tôi yêu chúng tôi một số điểm ở đây tại SO. – aaronasterling

+2

-1: đây không phải là wiki. –

+0

@AaronMcSmooth 'self._value' có thể chứa bất kỳ loại dữ liệu nào vì vậy tôi muốn có tất cả các phương pháp khả dụng có sẵn. –

Trả lời

11

Nếu tôi hiểu chính xác bạn, bạn đang tìm kiếm một cách dễ dàng để ủy quyền phương thức của đối tượng cho thuộc tính của đối tượng đó?

Bạn có thể tránh được một số repetitiveness bằng cách định nghĩa một trang trí:

def delegate(method, prop): 
    def decorate(cls): 
     setattr(cls, method, 
      lambda self, *args, **kwargs: 
       getattr(getattr(self, prop), method)(*args, **kwargs)) 
     return cls 
    return decorate 

Sau đó bạn có thể áp dụng trang trí cho từng phương pháp mà bạn muốn giao:

@delegate('__len__', '_content') 
@delegate('__getitem__', '_content') 
class MyList(object): 
    def __init__(self, content): 
     self._content = content 

spam = MyList([1,2,3,4,5]) 

len(spam) # prints "5" 

spam[0] # prints "1" 

Bạn có thể có thể đơn giản hóa nó hơn nữa bằng cách sửa đổi trang trí để lấy nhiều tên phương thức làm đối số.

Nếu bạn muốn lớp của bạn hoạt động như một trình bao bọc đầy đủ, bạn có thể ghi đè lên phương thức __getattr__ của lớp để kiểm tra đối tượng được bao bọc trước khi không thành công. Điều đó sẽ mô phỏng hành vi của các lớp con không thừa kế thực tế.

+0

Tôi nghĩ rằng trọng số '__getattr__' là gần gũi hơn với những gì tôi đang tìm kiếm nhưng tôi thấy giá trị trong tùy chọn trang trí là tốt. Bây giờ tôi chỉ cần hiểu sự khác nhau giữa '__getattr__' và' __getattribute__': http://docs.python.org/reference/datamodel.html#object.__getattribute__ –

0

Bạn cần quá tải phương thức __add__ để có được hành vi c1 + c2 mà bạn muốn.

Xem here để biết thông tin về tất cả chúng là gì.

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