2012-01-19 22 views
5

Làm cách nào để bạn có thể tạo phương thức lớp tĩnh sau khi lớp được xác định? Nói cách khác, tại sao trường hợp thứ ba thất bại?Tạo staticmethod từ phương thức hiện có bên ngoài lớp học? (lỗi "phương pháp không liên kết")

 

>>> class b: 
... @staticmethod 
... def foo(): 
... pass 
... 
>>> b.foo() 
>>> class c: 
... def foo(): 
... pass 
... foo = staticmethod(foo) 
... 
>>> c.foo() 
>>> class d: 
... def foo(): 
... pass 
... 
>>> d.foo = staticmethod(d.foo) 
>>> d.foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unbound method foo() must be called with d instance as first argument (got nothing instead) 

Trả lời

6

Sau khi lớp được định nghĩa, foo là một đối tượng cởi ra phương pháp (một wrapper rằng quan hệ chức năng đến lớp), không phải là một chức năng. Các wrapper sẽ cố gắng để vượt qua một thể hiện của lớp (self) với chức năng như là đối số đầu tiên và do đó, nó phàn nàn rằng bạn đã không cho nó một.

staticmethod() chỉ nên được sử dụng với chức năng. Mặc dù lớp học vẫn đang được xác định (như trong số bc) foo() của bạn vẫn là một hàm, vì trình bao bọc phương thức được áp dụng khi định nghĩa lớp hoàn tất.

Có thể trích xuất hàm từ đối tượng phương thức không gắn kết, áp dụng staticmethod() và gán lại cho lớp.

class d(object): 
    def foo(): 
     pass 

d.foo = staticmethod(d.foo.im_func) 

Trong Python 3, không có phương pháp thể hiện không ràng buộc (phương thức được lưu trữ trên lớp là hàm thuần). Vì vậy, mã ban đầu của bạn thực sự có thể làm việc tốt trên Python 3.

Một cách hoạt động trên cả hai Python 2 và Python 3 là:

d.foo = staticmethod(d.__dict__['foo']) 

(Nó cũng tránh việc tạo ra và loại bỏ các wrapper phương pháp.)

+0

Không nên là 'd.foo.im_func'? –

+0

Vâng, cảm ơn. Đã sửa! – kindall

+0

Vâng, bạn cần đánh dấu chúng bằng 'staticmethod' để gọi chúng tương đương với các cá thể, không chỉ riêng lớp đó. 'd.foo()' làm việc có hoặc không có gói 'staticmethod', nhưng' d(). foo() 'sẽ phát nổ (nó sẽ cố gắng truyền' self' mà 'foo' không chấp nhận). Chắc chắn, không có tính năng liên quan đến cá thể nào cần gọi chúng trên một cá thể, nhưng đối với DRY, các phương thức tham chiếu phương thức tĩnh có thể và nên gọi nó là 'self.foo()' thay vì đặt tên lớp một cách rõ ràng. – ShadowRanger

5

Bạn phải chuyển hàm, chứ không phải phương thức không liên kết.

>>> class d: 
... def foo(): 
...  pass 
... 
>>> d.foo = staticmethod(d.foo.im_func) 
>>> d.foo() 
Các vấn đề liên quan