2012-04-29 26 views
10

Tôi muốn chỉ định thực hiện chức năng động.Tự động gán chức năng triển khai thực hiện trong Python

Hãy bắt đầu với những điều sau đây:

class Doer(object): 

    def __init__(self): 
     self.name = "Bob" 

    def doSomething(self): 
     print "%s got it done" % self.name 

def doItBetter(self): 
    print "Done better" 

Trong các ngôn ngữ khác, chúng tôi sẽ làm cho doItBetter một chức năng ẩn danh và gán nó vào đối tượng. Nhưng không hỗ trợ cho các hàm ẩn danh trong Python. Thay vào đó, chúng tôi sẽ cố gắng thực hiện một cá thể của lớp callable, và gán vào trong lớp:

class Doer(object): 

    def __init__(self): 
     self.name = "Bob" 

class DoItBetter(object): 

    def __call__(self): 
     print "%s got it done better" % self.name 

Doer.doSomething = DoItBetter() 
doer = Doer() 
doer.doSomething() 

Đó mang lại cho tôi điều này:

Traceback (most recent call last): Line 13, in doer.doSomething() Line 9, in call print "%s got it done better" % self.name AttributeError: 'DoItBetter' object has no attribute 'name'

Cuối cùng, tôi đã cố gắng gán callable với trường hợp đối tượng như một thuộc tính và gọi đó là:

class Doer(object): 

    def __init__(self): 
     self.name = "Bob" 

class DoItBetter(object): 

    def __call__(self): 
     print "%s got it done better" % self.name 


doer = Doer() 
doer.doSomething = DoItBetter() 
doer.doSomething() 

này kHÔNG làm việc miễn là tôi không tham khảo tự trong DoItBetter, nhưng khi tôi làm điều đó mang lại cho tôi một lỗi tên trên self.name bởi vì nó tham khảo số self của người gọi, không phải là lớp sở hữu self. Vì vậy, tôi đang tìm một cách pythonic để gán một hàm ẩn danh cho một hàm lớp hoặc phương thức cá thể, trong đó cuộc gọi phương thức có thể tham chiếu đến đối tượng self của đối tượng.

+0

Không có gì sai với cách tiếp cận đầu tiên mà bạn từ chối. Tại sao bạn làm cho nó quá phức tạp? –

+2

Lỗi của bạn thực sự là lạ - bạn đang cố gắng chạy một tập lệnh Python với một thông dịch viên ruby? (Tệp của bạn được gọi là 'prog.rb',' .py' là phần mở rộng của tệp Python). Lỗi chắc chắn không phải là từ Python - 'self' không phải là một từ khóa trong Python. –

+0

Lỗi lầm của tôi- chạy nó trên một codepad trực tuyến với cài đặt ruby- cố định – Yarin

Trả lời

23

tiếp cận đầu tiên của bạn là OK, bạn chỉ cần gán các chức năng để các lớp:

class Doer(object): 
    def __init__(self): 
     self.name = "Bob" 

    def doSomething(self): 
     print "%s got it done" % self.name 

def doItBetter(self): 
    print "%s got it done better" % self.name 

Doer.doSomething = doItBetter 

chức năng Anonymous không có gì để làm với điều này (bằng cách này, Python hỗ trợ chức năng ẩn danh đơn giản bao gồm các biểu thức đơn , xem lambda).

+0

+1 ẩn danh không quan trọng ở đây - tất cả những vấn đề là bạn có thể gán chức năng. –

+0

Cảm ơn công trình này tuyệt vời - không chắc tại sao tôi nghĩ nó không phải là – Yarin

19

Câu trả lời của yak hoạt động tốt nếu bạn muốn thay đổi điều gì đó cho mọi trường hợp của một lớp học.

Nếu bạn muốn thay đổi phương pháp duy nhất cho một cụ thể dụ của đối tượng, chứ không phải cho toàn bộ lớp, bạn sẽ cần phải sử dụng constructor MethodType loại để tạo ra một phương pháp ràng buộc:

from types import MethodType 

doer.doSomething = MethodType(doItBetter, doer, Doer) 
+0

@ Amber- Cảm ơn bạn vì điều này – Yarin

+1

Ít nhất trong Python 3, nó phải là 'doer.doSomething = MethodType (doItBetter, doer)'. Giải thích tốt về các trường hợp khác nhau cho các phương pháp và chức năng được đưa ra trong http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance – yanlend

+0

@yanlend câu hỏi này đã được yêu cầu Python 2. – Amber