2014-04-05 16 views
6

Tôi có một nền tảng bằng Python (mặc dù hoàn toàn tự học, vì vậy tôi có thể có một số thói quen xấu hoặc quan niệm sai), và tôi đang cố gắng tìm hiểu Ruby để mở rộng phạm vi của mình.Lập trình meta bằng Python - thêm phương thức đối tượng

Tôi đã đọc qua một số so sánh và thấy rất nhiều khẳng định rằng "Python không thể lập trình meta" (hoặc, ít gây khó chịu hơn, "Python không thể lập trình meta đơn giản như Ruby"). Vì vậy, tôi đã đi và nhanh chóng đọc về metaprogramming, và đi xa với ấn tượng rằng, về cơ bản, chỉnh sửa các phương pháp/hành vi của các lớp học/đối tượng của bạn trong thời gian chạy (xin vui lòng sửa tôi nếu tôi không chính xác!).

Tôi đã có ấn tượng rằng, vì Python là động, điều đó không phải là vấn đề. Tuy nhiên, tôi chạy mã kiểm tra sau, mà không đưa ra câu trả lời tôi mong đợi:

>>> class foo: 
...  def make_hello_method(self): 
...    def hello(obj): 
...      print 'hello' 
...    self.hello = hello 
... 
>>> f = foo() 
>>> f.hello() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: foo instance has no attribute 'hello' 
>>> f.make_hello_method() 
>>> f.hello() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: hello() takes exactly 1 argument (0 given) 

Tôi đã theo ấn tượng rằng mọi phương pháp của một đối tượng được tự động thông qua các đối tượng chính nó như là đối số đầu tiên (do đó các yêu cầu liên tục để xác định các phương thức đối tượng là (self, [...])). Làm thế nào đến f không được chuyển đến hello()?

+0

Duplicate của http://stackoverflow.com/questions/972/ add-a-method-to-an-existing-đối tượng – spinlok

Trả lời

5

Bạn cần biến nó thành phương pháp instancemethod. Có một lớp học để làm điều đó trong mô-đun types. Điều này sẽ làm việc:

self.hello = types.MethodType(hello, self) 
+0

Ah, gotcha. Kiểu gọi() trên 'f.make_hello_method' và trên' f.hello' tạo sự khác biệt rõ ràng. Cảm ơn bạn! – scubbo

+0

@scubbo: Nếu bạn muốn thêm phương thức vào lớp thay vì chỉ một ví dụ, bạn cần thay vào đó sử dụng một cái gì đó như 'setattr (foo," hello ", hello)', nó sẽ thêm nó vào lớp, tất cả các phiên bản hiện có, cũng như các phiên bản mới được tạo. – martineau

2

Thấy như bạn đang sử dụng Python 2, bạn có thể sử dụng các mô-đun new để làm cho công việc này:

self.hello = new.instancemethod(hello, self, foo) 
Các vấn đề liên quan