2009-07-17 33 views
5

में स्थानीय नेमस्पेस को कैसे संशोधित करें मैं पाइथन में फ़ंक्शन के स्थानीय नेमस्पेस को कैसे संशोधित कर सकता हूं? मुझे पता है कि स्थानीय() इसके अंदर बुलाए जाने पर फ़ंक्शन के स्थानीय नेमस्पेस को लौटाते हैं, लेकिन मैं ऐसा कुछ करना चाहता हूं (मेरे पास ऐसा कारण है कि मैं ऐसा करना चाहता हूं जहां जी f तक पहुंच योग्य नहीं है, लेकिन यह देना तेज़ है एक छोटी सी, बेवकूफ उदाहरण समस्या को वर्णन करने):पाइथन

def g(): 
    pass 

def f(): 
    g() 

f.add_to_locals({'g':g}) 
+0

अपने अंतिम यह अजीब तकनीक का उपयोग कर लक्ष्य क्या है काम करने के लिए लगता है? आप एफ() से पहले जी() को परिभाषित क्यों नहीं कर सकते? –

+0

मैंने पहले रनटाइम पर एक फ़ंक्शन के नामस्थान के साथ गड़बड़ करने की कोशिश की है (परीक्षण/मॉकिंग के लिए) और असफल ... बस FYI। –

+0

क्या बिल्ली 'add_to_locals' है? यह मेरे लिए अस्तित्व में प्रतीत नहीं होता है। 'विशेषता त्रुटि:' फ़ंक्शन 'ऑब्जेक्ट में कोई विशेषता नहीं है' add_to_locals'' –

उत्तर

3

के बाद से समारोह लागू नहीं है, यह कोई "स्थानीय" स्टैक फ्रेम है, फिर भी। सबसे सरल उपाय एक वैश्विक संदर्भ का उपयोग करना है:

handler = None 
def f(): 
    handler() 

def g(): pass 

handler = g 

या आप समारोह वस्तु पर जी सेट कर सकते हैं:

f.g = g 

लेकिन मुझे यकीन है कि कैसे आप के भीतर से समारोह वस्तु प्राप्त कर सकते हैं नहीं कर रहा हूँ समारोह स्वयं यदि यह एक विधि थी, तो आप self का उपयोग करेंगे।

+0

आप * वास्तव में * समारोह के अंदर समारोह वस्तु का उपयोग करना चाहता है, तो आप का निरीक्षण इस्तेमाल कर सकते हैं: आयात का निरीक्षण आयात pprint डीईएफ़ fn(): फ्रेम = inspect.currentframe() प्रिंट frame.f_globals [फ्रेम .f_code.co_name] .g fn.g = 'हैलो' एफएन() – Ivo

+0

यह वर्ग कार्यों, नेस्टेड फ़ंक्शंस/क्लोजर, और लैम्ब्डा, और सजाए गए कुछ भी के लिए टूटा हुआ है - यह सजावटी के रैपिंग फ़ंक्शन को वापस नहीं करेगा, न कि वास्तविक कार्य –

+0

क्या होगा यदि 'f' एक वर्ग/आवृत्ति विधि है? –

1

निष्पादित नहीं किया गया कोई फ़ंक्शन कोई स्थानीय नहीं है; जब आप फ़ंक्शन चलाते हैं तो स्थानीय संदर्भ बनाया जाता है, और जब यह निकलता है तो नष्ट हो जाता है, इसलिए फ़ंक्शन के बाहर से संशोधित करने के लिए कोई "स्थानीय नेमस्पेस" नहीं होता है।

आप कुछ इस तरह कर सकते हैं, हालांकि:

def f(): 
    g = [1] 
    def func(): 
     print g[0] 
    return func, g 

f, val = f() 
f() 
val[0] = 2 
f() 

यह एक सरणी का उपयोग करता है एक संदर्भ अनुकरण करने के लिए।

+2

इस साइट को वास्तव में -1 वोटों के लिए स्पष्टीकरण की आवश्यकता होनी चाहिए, इसलिए लोग बिना किसी कारण के अज्ञात रूप से सही उत्तरों को वोट नहीं दे सकते हैं। –

2

मुझे लगता है कि आप इसे पूरी तरह से अलग बिंदु से निपटने में समस्या का समाधान कर सकते हैं।
कार्य उनके ऑब्जेक्ट्स के साथ ऑब्जेक्ट हैं; इसलिए, आप च को ग्राम जोड़ सकते हैं, और प्रयोग यह:

def g(): 
    print "g" 

def f(): 
    f.g() 

f.g = g 
+0

बहुत ही सुरुचिपूर्ण समाधान। +1 – Josip

+0

यह केवल वैश्विक कार्यों के लिए काम करता है; एफ के भीतर से विश्वसनीय रूप से एफ तक पहुंचने का कोई तरीका नहीं है। –

+0

क्या आप इसे विस्तारित कर सकते हैं? पायथन फ़ंक्शन ऑब्जेक्ट्स हैं, और स्थानीय या वैश्विक होने पर कोई अंतर नहीं है - जब तक कि आप _methods_ का मतलब न लें, लेकिन यह एक पूरी तरह से अलग कहानी है, और ओपी क्या नहीं मांग रहा था। –

3

आप क्यों नहीं बस f() लिए एक तर्क जोड़ सकते हैं और g() के लिए एक संदर्भ में उत्तीर्ण नहीं होते?

def g(): 
    pass 

def f(func): 
    func() 

f(g) 
2

मुझे लगता है कि आप ऐसा करना चाहते हैं, क्योंकि फ़ंक्शन फ़ को आपके द्वारा परिभाषित नहीं किया गया है, लेकिन कुछ अन्य मॉड्यूल द्वारा। तो आप बदलना चाहते हैं कि कैसे f() काम करता है। विशेष रूप से, जब आप जी कहा जाता है तो आप उसे बदलना चाहते हैं।

तो मैं इस सुझाव देंगे:

import thirdpartypackage 

def mynewg(): 
    pass 

thirdpartypackage.g = mynewg 

इस मॉड्यूल thirdpartypackage के लिए वैश्विक ग्राम बदल जाएगा। तो जब thirdpartypackage.f() अब कहा जाता है, तो यह g() के बजाय mynewg() को कॉल करेगा।

यदि यह इसे हल नहीं करता है, तो शायद जी() वास्तव में f(), या कुछ के साथ आयात किया जाता है। फिर समाधान यह है:

import thirdpartypackage 

def mynewg(): 
    pass 

deg mynewf(): 
    mynewg() 

thirdpartypackage.f = mynewf 

यही है कि आप एक संशोधित संस्करण के साथ पूरी तरह से f() को ओवरराइड करते हैं जो आप चाहते हैं।

8

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

एक विकल्प फ़ंक्शन के मॉड्यूल के नामस्थान में आपके फ़ंक्शन को इंजेक्ट करने के लिए है। यह काम करेगा, लेकिन उस मॉड्यूल में प्रत्येक फ़ंक्शन को प्रभावित करेगा जो केवल एक फ़ंक्शन के बजाय चर का उपयोग करता है।

केवल एक समारोह को प्रभावित करने के लिए, आपको कहीं और func_globals को इंगित करने की आवश्यकता है। दुर्भाग्य से, यह केवल पढ़ने के लिए संपत्ति है, लेकिन आप एक ही शरीर के साथ समारोह पुनः द्वारा आप क्या चाहते हैं कर सकते हैं, लेकिन एक अलग वैश्विक नामस्थान:

import new 
f = new.function(f.func_code, {'g': my_g_function}, f.func_name, f.func_defaults, f.func_closure) 

च अब सिवाय इसके कि यह दिखाई देगा, indentical हो जाएगा प्रदान किए गए निर्देश में ग्लोबल्स के लिए। ध्यान दें कि यह पूरे वैश्विक नामस्थान को पुनर्निर्मित करता है - यदि वहां चर हैं तो f देखता है, सुनिश्चित करें कि आप उन्हें भी प्रदान करते हैं। हालांकि यह भी काफी हैकी है, और शायद cpython के अलावा अजगर के संस्करणों पर काम नहीं कर सकता है।

+1

मुझे नहीं पता कि यह "अच्छा" कोड है, लेकिन यह वही था जो मैं चाहता था। मैं एक कोडबेस को दूसरे में परिवर्तित कर रहा हूं और मैं दूसरी भाषा से एक भाषा निर्माण अनुकरण करने में सक्षम होना चाहता था। दूसरी भाषा कोड पैकेज कर सकती है और उस कोड को नामस्थान से जोड़ या निकाल सकती है। यह विभिन्न कार्यों को ओवरराइड करने में उपयोगी है। तो यह फैशन की तरह एक ढेर में नामस्थान का उपयोग करता है। यह सबसे नज़दीकी चीज है जिसे मैं पा सकता हूं जो मुझे कुशलतापूर्वक ऐसा करने की अनुमति देगा। धन्यवाद – Demolishun

+0

यह 'नई' लाइब्रेरी क्या है? –

+0

'exec' या' locals() के साथ क्या गलत है। अद्यतन (डी) '? –

0

यह

def add_to_locals(l): 
    l['newlocal'] = 1 

add_to_locals(locals()) 
assert newlocal 
+0

यह एक फ़ंक्शन के अंदर काम नहीं करता है। यह नामस्थान में मान नहीं जोड़ता है। – Demolishun