2012-11-01 12 views
27

क्षमा करें यदि यह प्रश्न पहले ही उठाया गया है और उत्तर दिया गया है। मुझे क्या करना है अवधारणा में बहुत आसान है, लेकिन दुर्भाग्य से मैं इसके लिए ऑनलाइन जवाब नहीं ढूंढ पाया।कस्टम नामों के साथ पायथन गतिशील फ़ंक्शन निर्माण

मुझे रनटाइम पर कस्टम नामों के साथ पायथन (पायथन 2.7) में गतिशील फ़ंक्शन बनाने की आवश्यकता है। प्रत्येक समारोह के शरीर को रनटाइम पर भी निर्माण करने की आवश्यकता होती है लेकिन यह सभी कार्यों के लिए (लगभग) समान होती है।

मैं नामों की एक सूची के साथ शुरू करता हूं।

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

ध्यान दें कि FUNC_NAME सूची, मनमाने ढंग से नामों की सूची पकड़ इतना नाम बस func1, func2, func3 नहीं किया जाएगा कर सकते हैं, ....

मैं परिणाम होना चाहते हैं:

def func1(*args): 
     ... 

    def func2(*args): 
     ... 

    def func3(*args): 
     ... 

मुझे ऐसा करने की आवश्यकता है कि प्रत्येक फ़ंक्शन का नाम एक परीक्षण मामले से मेल खाता है जिसे बाद में बाहरी दुनिया से बुलाया जाता है।

अद्यतन: कोई उपयोगकर्ता इनपुट नहीं है। मैं एक बहुत बड़े मॉड्यूल के दो सिरों को बांध रहा हूँ। एक अंत निर्धारित करता है कि परीक्षण के मामले क्या हैं और अन्य चीजों के साथ, परीक्षण मामलों के नामों की एक सूची पॉप्युलेट करता है। दूसरा अंत कार्य स्वयं है, जिसमें टेस्ट केस के नाम से 1: 1 मैपिंग होना चाहिए। तो मेरे पास टेस्ट केस का नाम है, मुझे पता है कि मैं प्रत्येक टेस्ट केस के साथ क्या करना चाहता हूं, मुझे सिर्फ उन कार्यों को बनाने की ज़रूरत है जिनके पास टेस्ट केस हैं। चूंकि टेस्ट केस का नाम रनटाइम पर निर्धारित होता है, इसलिए उन परीक्षण मामलों के आधार पर फ़ंक्शन निर्माण रनटाइम पर भी होना चाहिए।

अद्यतन: मैं इस कस्टम नामित कार्यों को कक्षा में भी लपेट सकता हूं यदि इससे चीज़ें आसान हो जाएंगी।

मैं स्ट्रिंग में फ़ंक्शंस की सामग्री को हार्ड-कोड कर सकता हूं (क्योंकि वे लगभग समान हैं), या मैं पहले परिभाषित बेस क्लास से इसे आधार कर सकता हूं। बस इस सामग्री के साथ कार्यों को पॉप्युलेट करने के बारे में जानने की जरूरत है।

उदाहरण के लिए:

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

अग्रिम धन्यवाद,

महदी

उत्तर

1

आप eval उपयोग कर सकते हैं; आप प्रत्येक फ़ंक्शन की पायथन परिभाषा वाली स्ट्रिंग का निर्माण करेंगे (यानी def func1 से शुरू होने वाली एक मल्टीलाइन स्ट्रिंग ....) और फिर आप eval करेंगे।

लेकिन मैं इस तरह के प्रत्येक फ़ंक्शन के लिए एक अद्वितीय नाम उत्पन्न करूंगा (उदा। genfun345)। ऐसे नामों के लिए कुछ अनचेक उपयोगकर्ता इनपुट का उपयोग न करें। क्योंकि यदि नाम पायथन में कुछ ज्ञात नाम के समान है, तो आपदा को डीबग करना मुश्किल हो रहा है।

क्या आप उन इनपुटों पर भरोसा करते हैं जिनसे इन कार्यों को बनाया जाता है? क्या आपको मैलवेयर या दुर्व्यवहार की परवाह है?

विकिपीडिया पर hygenic macros पढ़ें।

+0

कोई उपयोगकर्ता इनपुट है यहाँ एक उदाहरण है कि एक वर्ग पर तरीकों को परिभाषित करता है। मैं एक बहुत बड़े मॉड्यूल के दो सिरों को बांध रहा हूँ। एक अंत निर्धारित करता है कि परीक्षण के मामले क्या हैं और अन्य चीजों के साथ, परीक्षण मामलों के नामों की एक सूची पॉप्युलेट करता है। दूसरा अंत कार्य स्वयं है, जिसमें टेस्ट केस के नाम से 1: 1 मैपिंग होना चाहिए। तो मेरे पास टेस्ट केस का नाम है, मुझे पता है कि मैं प्रत्येक टेस्ट केस के साथ क्या करना चाहता हूं, मुझे सिर्फ उन कार्यों को बनाने की ज़रूरत है जिनके पास टेस्ट केस हैं। चूंकि टेस्ट केस का नाम रनटाइम पर निर्धारित होता है, इसलिए उन परीक्षण मामलों के आधार पर फ़ंक्शन निर्माण रनटाइम पर भी होना चाहिए। – mahdiolfat

33

जो आप वर्णन करते हैं, उसके लिए मुझे नहीं लगता कि आपको eval या macros में उतरने की आवश्यकता है - बंद करके फ़ंक्शन इंस्टेंस बनाना ठीक काम करना चाहिए।उदाहरण:

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 

हालांकि, आप शायद उन कार्यों को नाम से कुछ दायरे में जोड़ना चाहेंगे ताकि आप उन्हें नाम से एक्सेस कर सकें।

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

सरल और काम करता है। –

6

शायद बात इस तरह का करने के लिए आत्मनिरीक्षण का एक प्रकार है, लेकिन मुझे नहीं लगता कि यह समस्या का pythonic दृष्टिकोण होगा।

मुझे लगता है कि आपको पहले स्तर के नागरिकों के रूप में पाइथन में कार्यों की प्रकृति का लाभ उठाना चाहिए। जैसा कि आप चाहें फ़ंक्शन सामग्री को कस्टमाइज़ करने के लिए शेन होलोय ने इंगित किया है। फिर गतिशील नाम बाध्यकारी के लिए, एक शब्दकोश का उपयोग करें जिनकी चाबियाँ गतिशील रूप से परिभाषित नाम हैं, और मान स्वयं कार्य होंगे।

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) 

आशा है कि यह आपके उपयोग के मामले में समझ में आता है।

1

मैं सही ढंग से अपनी आवश्यकताओं को समझने कर रहा हूँ, तो यह लगता है कि आप सिर्फ गतिशील मौजूदा कार्यों नए या वैकल्पिक नाम प्रदान करना चाहते हैं - जो मामले कुछ निम्नलिखित लाइनों के साथ में काम करना चाहिए:

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

आपकी प्रतिक्रिया के लिए धन्यवाद। लेकिन मामला वह नहीं है। वे मौजूदा कार्य नहीं हैं, और इसके अलावा, गतिशील रूप से बनाए जाने वाले कार्यों की संख्या भी अज्ञात है (केवल रनटाइम पर ज्ञात है)। – mahdiolfat

+0

यदि आप "फ़ंक्शन की सामग्री को हार्ड-कोड" कर सकते हैं तो आप उस सामग्री को 'def xxx (yyy):' apy फ़ाइल में 'से पहले भी कर सकते हैं और इसे एक मौजूदा फ़ंक्शन बना सकते हैं - आपको क्या लगता है कि आप' इसे स्ट्रिंग में डालकर और गतिशील रूप से इसमें से एक फ़ंक्शन बनाकर प्राप्त कर रहे हैं? – martineau

+0

मुझे लगता है कि आपने जो कुछ करने की कोशिश कर रहा हूं उसे गलत समझा है और वास्तव में मेरे प्रश्न का उत्तर नहीं दिया है, लेकिन कुछ और करने के लिए कह रहा है। फिर भी धन्यवाद। मैंने पहले ही अपनी समस्या हल कर ली है। – mahdiolfat

10

शेन के जवाब पर विस्तार करना क्योंकि मुझे एक ही समस्या के समाधान की तलाश करते समय यह प्रश्न अभी मिला है। चर के दायरे के साथ ख्याल रखना। आप दायरे को परिभाषित करने के लिए जेनरेटर फ़ंक्शन का उपयोग कर स्कोप समस्याओं से बच सकते हैं।

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) 

उपयोग में::

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> 
संबंधित मुद्दे