2012-11-01 45 views
27

Xin lỗi nếu câu hỏi này đã được nêu ra và trả lời. Những gì tôi cần làm là rất đơn giản trong khái niệm, nhưng tiếc là tôi đã không thể tìm thấy một câu trả lời cho nó trực tuyến.Tạo chức năng động Python với tên tùy chỉnh

Tôi cần tạo các hàm động trong Python (Python2.7) với tên tùy chỉnh khi chạy. Phần thân của mỗi hàm cũng cần được xây dựng trong thời gian chạy nhưng nó gần như giống nhau cho tất cả các hàm.

Tôi bắt đầu với danh sách tên.

func_names = ["func1", "func2", "func3"] 

Lưu ý rằng danh sách FUNC_NAME có thể giữ một danh sách tên tùy ý, vì vậy những cái tên sẽ KHÔNG đơn giản là Func1, Func2, func3, ....

Tôi muốn kết quả là:

def func1(*args): 
     ... 

    def func2(*args): 
     ... 

    def func3(*args): 
     ... 

Lý do tôi cần làm điều này là mỗi tên hàm tương ứng với một trường hợp thử nghiệm mà sau đó được gọi từ thế giới bên ngoài.

cập nhật: Không có đầu vào của người dùng. Tôi đang buộc hai đầu của một mô-đun lớn hơn nhiều. Một đầu xác định các trường hợp thử nghiệm là gì và trong số những thứ khác, điền một danh sách các tên của các trường hợp thử nghiệm. Đầu kia là bản thân các hàm, mà phải có ánh xạ 1: 1 với tên của trường hợp thử nghiệm. Vì vậy, tôi có tên của các trường hợp thử nghiệm, tôi biết những gì tôi muốn làm với mỗi trường hợp thử nghiệm, tôi chỉ cần tạo ra các chức năng có tên của các trường hợp thử nghiệm. Vì tên của các trường hợp thử nghiệm được xác định trong thời gian chạy, việc tạo ra hàm dựa trên các trường hợp thử nghiệm đó cũng phải ở thời gian chạy.

cập nhật: Tôi cũng có thể bọc các hàm được đặt tên tùy chỉnh này trong một lớp nếu điều đó có thể giúp mọi thứ trở nên dễ dàng hơn.

Tôi có thể mã hóa cứng nội dung của các hàm (vì chúng hầu như giống nhau) trong một chuỗi, hoặc tôi có thể căn cứ nó khỏi một lớp cơ sở đã được định nghĩa trước đó. Chỉ cần biết cách điền các hàm với nội dung này.

Ví dụ:

func_content = """ 
        for arg in args: 
         print arg 
        """ 

Cảm ơn trước,

Mahdi

Trả lời

1

Bạn có thể muốn sử dụng eval; bạn sẽ xây dựng chuỗi chứa định nghĩa Python của mỗi hàm (tức là chuỗi nhiều dòng bắt đầu bằng def func1 ....) và sau đó bạn sẽ là eval nó.

Nhưng tôi sẽ tạo một tên duy nhất cho mỗi chức năng như vậy (ví dụ: genfun345). Không sử dụng một số đầu vào người dùng không được kiểm soát cho các tên như vậy. Bởi vì nếu tên giống với tên được biết đến trong Python, bạn sẽ gặp khó khăn trong việc gỡ lỗi.

Bạn có tin tưởng các yếu tố đầu vào mà từ đó các chức năng này được thực hiện không? Bạn có quan tâm đến phần mềm độc hại hoặc lạm dụng không?

Đọc khoảng hygenic macros trên wikipedia.

+0

Không có đầu vào người dùng. Tôi đang buộc hai đầu của một mô-đun lớn hơn nhiều. Một đầu xác định các trường hợp thử nghiệm là gì và trong số những thứ khác, điền một danh sách các tên của các trường hợp thử nghiệm. Đầu kia là bản thân các hàm, mà phải có ánh xạ 1: 1 với tên của trường hợp thử nghiệm. Vì vậy, tôi có tên của các trường hợp thử nghiệm, tôi biết những gì tôi muốn làm với mỗi trường hợp thử nghiệm, tôi chỉ cần tạo ra các chức năng có tên của các trường hợp thử nghiệm. Vì tên của các trường hợp thử nghiệm được xác định trong thời gian chạy, việc tạo ra hàm dựa trên các trường hợp thử nghiệm đó cũng phải ở thời gian chạy. – mahdiolfat

33

Đối với những gì bạn mô tả, tôi không nghĩ rằng bạn cần phải đi sâu vào eval hoặc macro - tạo ra các thể hiện chức năng bằng cách đóng nên hoạt động tốt.Ví dụ:

def bindFunction1(name): 
    def func1(*args): 
     for arg in args: 
      print arg 
     return 42 # ... 
    func1.__name__ = name 
    return func1 

def bindFunction2(name): 
    def func2(*args): 
     for arg in args: 
      print arg 
     return 2142 # ... 
    func2.__name__ = name 
    return func2 

Tuy nhiên, bạn có thể muốn thêm các chức năng đó theo tên vào phạm vi nào đó để bạn có thể truy cập chúng theo tên.

>>> print bindFunction1('neat') 
<function neat at 0x00000000629099E8> 
>>> print bindFunction2('keen') 
<function keen at 0x0000000072C93DD8> 
+0

Đơn giản và hoạt động. –

6

Có thể có một loại nội tâm để làm điều này, nhưng tôi không nghĩ đó sẽ là phương pháp tiếp cận pythonic cho vấn đề.

Tôi nghĩ bạn nên tận dụng bản chất của các hàm trong python như công dân cấp một. Sử dụng các bao đóng như Shane Holloway chỉ, để tùy chỉnh các nội dung chức năng theo ý muốn. Sau đó, để liên kết tên động, hãy sử dụng từ điển có khóa là tên được xác định động và các giá trị sẽ là chính các hàm đó.

def function_builder(args): 
    def function(more_args): 
     #do stuff based on the values of args 
    return function 

my_dynamic_functions = {} 
my_dynamic_functions[dynamic_name] = function_builder(some_dynamic_args) 

#then use it somewhere else 
my_dynamic_functions[dynamic_name](the_args) 

Hy vọng điều đó có ý nghĩa đối với trường hợp sử dụng của bạn.

1

Nếu tôi hiểu yêu cầu của bạn một cách chính xác, có vẻ như bạn chỉ muốn để tự động gán chức năng tên mới hoặc thay thế hiện tại - trong trường hợp này một cái gì đó dọc theo dòng sau đây phải thực hiện công việc:

import sys 

testcases = [] 
def testcase(f): 
    """ testcase function decorator """ 
    testcases.append(f) 
    return f 

@testcase 
def testcase0(*args): 
    print 'testcase0 called, args:', args 

@testcase 
def testcase1(*args): 
    print 'testcase1 called, args:', args 

@testcase 
def testcase2(*args): 
    print 'testcase2 called, args:', args 

def assign_function_names(func_names, namespace=None): 
    if namespace is None: 
     namespace = sys._getframe(1).f_globals # default to caller's globals 
    for name, func in zip(func_names, testcases): 
     func.__name__ = name # optional 
     namespace[name] = func 

assign_function_names(["funcA", "funcB", "funcC"]) 

funcA(1, 2, 3) 
funcB(4, 5) 
funcC(42) 
+0

Cảm ơn bạn đã trả lời. Nhưng đó không phải là trường hợp. Chúng không phải là các hàm hiện có, và hơn nữa, số lượng các hàm được tạo động cũng không được biết (chỉ được biết khi chạy). – mahdiolfat

+0

Nếu bạn có thể "mã hóa cứng nội dung của các hàm", bạn cũng có thể đứng trước nội dung đó bằng 'def xxx (yyy):' trong một tệp .py và làm cho nó trở thành một hàm tồn tại - bạn nghĩ gì ' tái đạt được bằng cách đặt nó trong chuỗi và tự động tạo ra một chức năng ra khỏi nó? – martineau

+0

Tôi nghĩ rằng bạn đã hiểu lầm những gì tôi đang cố gắng làm ở đây và không thực sự trả lời câu hỏi của tôi, nhưng tiếp tục nói để làm điều gì đó khác. Cảm ơn dù sao đi nữa. Tôi đã giải quyết được vấn đề của mình. – mahdiolfat

10

Mở rộng câu trả lời của Shane vì tôi vừa tìm thấy câu hỏi này khi tìm kiếm giải pháp cho một vấn đề tương tự. Cẩn thận với phạm vi của các biến. Bạn có thể tránh các vấn đề phạm vi bằng cách sử dụng một hàm máy phát để xác định phạm vi. Dưới đây là một ví dụ xác định phương pháp trên một lớp:

class A(object): 
    pass 

def make_method(name): 
    def _method(self): 
     print("method {0} in {1}".format(name, self)) 
    return _method 

for name in ('one', 'two', 'three'): 
    _method = make_method(name) 
    setattr(A, name, _method) 

Trong sử dụng:

In [4]: o = A() 

In [5]: o.one() 
method one in <__main__.A object at 0x1c0ac90> 

In [6]: o1 = A() 

In [7]: o1.one() 
method one in <__main__.A object at 0x1c0ad10> 

In [8]: o.two() 
method two in <__main__.A object at 0x1c0ac90> 

In [9]: o1.two() 
method two in <__main__.A object at 0x1c0ad10> 
Các vấn đề liên quan