2008-11-29 28 views
15

Tôi đang cố gắng để làm như sau trong python:lưu trữ chức năng python ràng buộc trong một đối tượng lớp

Trong một tập tin gọi là foo.py:

# simple function that does something: 
def myFunction(a,b,c): 
    print "call to myFunction:",a,b,c 

# class used to store some data: 
class data: 
    fn = None 

# assign function to the class for storage. 
data.fn = myFunction 

Và sau đó trong một tập tin gọi bar.py : nhập khẩu foo

d = foo.data 
d.fn(1,2,3) 

Tuy nhiên, tôi nhận được lỗi sau:

TypeError: unbound method f() must be called with data instance as first argument (got int instance instead)

Điều này là công bằng, tôi giả sử - python đang xử lý d.myFunction như một phương thức lớp. Tuy nhiên, tôi muốn nó coi nó như một hàm bình thường - vì vậy tôi có thể gọi nó mà không cần phải thêm một tham số 'self' chưa sử dụng vào định nghĩa myFunction.

Vì vậy, câu hỏi là:

Làm thế nào tôi có thể lưu trữ một hàm trong một lớp đối tượng không có chức năng bị ràng buộc vào lớp đó?

+0

Tôi nghĩ bạn định sử dụng: d.fn (1,2,3) và không phải d.myFunctions (1,2,3) –

+0

có, tôi nghĩ bạn có nghĩa là d.fn() – hop

+1

Giải pháp dưới đây, nhưng tại sao bạn muốn điều này? – orip

Trả lời

23
data.fn = staticmethod(myFunction) 

nên thực hiện thủ thuật.

+0

Đây là câu trả lời đúng và cú pháp, vì hàm được định nghĩa ở nơi khác. – tzot

0

Điều này dường như vô nghĩa đối với tôi. Tại sao không chỉ gọi myFunction khi bạn cần nó?

Nói chung, trong Python, chúng tôi sử dụng các mô-đun cho loại không gian tên này (tương phản với Java mà bạn không có lựa chọn nào). Và tất nhiên, myFunction đã bị ràng buộc với không gian tên mô-đun khi bạn xác định nó.

It is discussed somewhat in the answers to this question.

+0

Tôi đoán bạn có thể đính kèm một chức năng cụ thể vào một đối tượng, và sau đó nó được gọi bởi đối tượng mà không cần quan tâm đến một số chức năng mà nó thực sự đang gọi. –

+0

Hiểu sai những gì OP đã làm, không nhận thấy đó là một phương pháp lớp không phải là một phương pháp thể hiện. –

+0

Gọi nó khi cần thiết là tuyệt vời - nhưng khi thử nghiệm, bạn có thể giả lập chức năng gọi điện - điều này trở nên phức tạp hơn khi các thành viên gọi các chức năng vì khó nắm bắt phạm vi của chúng. – Glycerine

1

Những gì bạn có thể làm là:

d = foo.data() 
d.fn = myFunction 

d.fn(1,2,3) 

nào có thể không chính xác những gì bạn muốn, nhưng không làm việc.

0

Cảm ơn Andre đã trả lời - rất đơn giản!

Đối với những người bạn quan tâm, có lẽ tôi nên bao gồm toàn bộ bối cảnh của vấn đề. Ở đây nó là anyway:

Trong ứng dụng của tôi, người dùng có thể viết plugin trong python. Chúng phải định nghĩa một hàm với một danh sách tham số được xác định rõ, nhưng tôi không muốn áp đặt bất kỳ quy ước đặt tên nào vào chúng.

Vì vậy, miễn là người dùng viết một hàm với con số chính xác của các thông số và các loại, tất cả họ phải làm là một cái gì đó như thế này (hãy nhớ, đây là mã plugin):

# this is my custom code - all plugins are called with a modified sys.path, so this 
# imports some magic python code that defines the functions used below. 
from specialPluginHelperModule import * 

# define the function that does all the work in this plugin: 
def mySpecialFn(paramA, paramB, paramC): 
    # do some work here with the parameters above: 
    pass 

# set the above function: 
setPluginFunction(mySpecialFn) 

Cuộc gọi setPluginFunction lấy đối tượng hàm và đặt nó trong đối tượng lớp ẩn (cùng với các công cụ liên quan đến cấu hình plugin khác, ví dụ này đã được đơn giản hóa một chút). Khi ứng dụng chính muốn chạy hàm, tôi sử dụng mô-đun runpy để chạy mã plugin và sau đó trích xuất đối tượng lớp được đề cập ở trên - điều này mang lại cho tôi dữ liệu cấu hình và chức năng plugin để tôi có thể chạy nó một cách sạch sẽ không gian tên).

Toàn bộ quá trình này được lặp lại nhiều lần cho các plugin khác nhau trên cùng một đầu vào và dường như hoạt động rất tốt đối với tôi.

+0

"tất cả các plugin được gọi với sys.path đã sửa đổi" Bạn có sửa đổi sys.path tạm thời trong khối thử/cuối cùng hoặc có cách nào để "che" sys.path toàn cầu không? – haridsv

+4

Vui lòng sử dụng liên kết chỉnh sửa trên câu hỏi của bạn để thêm thông tin bổ sung. Nút Trả lời Bài đăng chỉ nên được sử dụng cho các câu trả lời hoàn chỉnh cho câu hỏi. – cpburnz

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