2010-03-25 14 views
15

क्या मैं एक फ़ंक्शन को परिभाषित कर सकता हूं जिसे कॉल किया जाता है, कॉलर के दायरे में नए स्थानीय लोगों को सम्मिलित करता है? मुझे लगता है कि कॉलर के स्थानीय() फ़ंक्शन में काम कर सकते हैं, लेकिन क्या ऐसा करने का कोई तरीका है जो मुझे के बिना ऐसा करने का कोई तरीका है?कॉलर के दायरे में चर इंजेक्शन?

+4

मान लीजिए कि कॉलर से अपने स्थानीय लोगों के साथ शहर जाने वाले कैली के जोखिमों को समझने की उम्मीद है। – jogloran

+0

स्पेगेटी –

+11

के लिए नुस्खा की तरह लगता है इसे "वापसी" कहा जाता है। –

उत्तर

8

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

इसके बजाय, आप कॉलर पास को एक स्पष्ट, वास्तविक, सामान्य dict (जिसे आप चाहते हैं locals() से शुरू किया जा सकता है) में हो सकता है, और कॉलर के उपयोग के लिए अभी भी उस कोड में आपके कोड के सभी बदलाव होंगे - - कॉलर के स्थानीय दायरे में बस "नए ब्रेनमेम्स" के रूप में नहीं, लेकिन कार्यक्षमता वही है कि कॉलर को x['foo'] या x.foo या (जैसा कि आप चाहें) का उपयोग करने की आवश्यकता है, केवल foo barename।

Btw, बल्कि dict अनुक्रमण सिंटेक्स की तुलना में विशेषता का उपयोग सिंटैक्स का उपयोग करने के लिए, आप कर सकते हैं:

class Bunch(object): pass 

... 

# caller code 
b = Bunch() 
thefun(b) 
print b.foo 

... 

# called function 
def thefun(b): 
    b.foo = 23 

यह भी एक छोटे से भिन्नता है, जिसमें मामले thefun dict अनुक्रमण वाक्य रचना के साथ काम करना चाहता है के साथ, को शामिल किया गया (कहें कि उसका शरीर b['foo'] = 23b.foo = 23 के बजाय है): उस स्थिति में, कॉलर को सादे thefun(b) के बजाय thefun(vars(b)) का उपयोग करने की आवश्यकता है, लेकिन यह बाद में b.foo एक्सेस सिंटैक्स के साथ काम करना जारी रख सकता है।

+0

ठीक है, ऐसा लगता है कि मैं जो चाहता हूं उसे करना वास्तव में संभव नहीं है। विशेषता पहुंच विचार के लिए धन्यवाद; अगर मेरे पास barenames (x) नहीं हो सकता है, तो अगली सबसे सुंदर चीज़ संभवतः एक्सेस (context.x) विशेषता है। – jogloran

+0

यह सच नहीं है, यह देखने के लिए बिल्टिन पायथन के निरीक्षण मॉड्यूल का उपयोग करके नीचे दिए गए उत्तर को देखें। पाइथन एक पूर्ण गतिशील भाषा है जिसे आप चाहें तो अपने स्वयं के दुभाषिया को ओवरराइट कर सकते हैं। मैं केवल उद्धरण देता हूं http://xkcd.com/353/ – Pykler

+0

एलेक्स सही है। @ पाइकलर का जवाब केवल एक विशिष्ट मामले में काम करता है, और आम तौर पर नहीं। – ferrouswheel

17

inspect module देखें, इसका उपयोग कॉलर के दायरे को नकल करने के लिए minimock द्वारा किया जाता है।

import inspect 
def mess_with_caller(): 
    stack = inspect.stack() 
    try: 
     locals_ = stack[1][0].f_locals 
    finally: 
     del stack 
    locals_['my_new_function'] = lambda : 'yaaaaaay' 


mess_with_caller() 
print my_new_function() 
>>> Output: 'yaaaaaay' 
+0

एफवाईआई: निरीक्षण एक पायथन मॉड्यूल में बनाया गया है। – Pykler

+0

पाइथन की शक्ति देखें! – Pykler

+2

डरावना काला जादू, लेकिन फिर भी शांत। काले जादू पर – Cerin

0

यह API बदले बिना संभव नहीं है, के रूप में CPython समारोह कॉल की अवधि के लिए तर्क सूची के लिए एक संदर्भ को बरकरार रखे हुए:

इस कोड क्या आप वास्तव में चाहते हैं चाहिए।

ऐसा करने का एक तरीका किसी ऑब्जेक्ट को पास करना है, और इसका उपयोग करते समय ऑब्जेक्ट की आंतरिक स्थिति को साफ़ करना है।

class Obj(object): 
    def __init__(self, state): 
     self.state = state 

def f(o): 
    # Do stuff with o.state 
    del o.state 
संबंधित मुद्दे