2009-06-25 11 views
29

इस स्निपेट पर विचार करें:सभी चर का एक dict जाओ और उनके मान

globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(**VARS_IN_SCOPE) 

myfunc(123) 

कहाँ VARS_IN_SCOPE dict मैं उस के बाद कर रहा हूँ globalVar, paramVar और localVar, होते हैं अन्य बातों के अलावा है।

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

Vars: 25, 123, 30

मैं format() करने के लिए **dict(globals().items() + locals().items()) पारित करके इस लक्ष्य को हासिल कर सकते हैं। क्या यह हमेशा सही है या क्या कुछ कोने के मामले हैं कि यह अभिव्यक्ति गलत तरीके से संभालती है?

प्रश्न को स्पष्ट करने के लिए पुनर्लेखन।

+0

आप ऐसा क्यों करना चाहते हैं? संभावना है कि आप जो भी करने की कोशिश कर रहे हैं उसे करने का एक बेहतर तरीका है। –

+0

मैंने सोचा कि स्निपेट इसे स्पष्ट कर देगा। मैं तारों के अंदर चर को interpolate करना चाहता हूँ। हर तरह से, एक बेहतर तरीका हो सकता है। कृपया एक को उत्तर के रूप में सुझाव देने के लिए स्वतंत्र महसूस करें। –

+0

क्षमा करें, स्निपेट समझा नहीं है ** क्यों ** आपको ऐसी चीज चाहिए। इसके अलावा, पैरामीटर बस स्थानीय हैं - यह एक अलग दायरा नहीं है। –

उत्तर

32

सबसे अच्छा तरीका है dict(globals(), **locals()) है।

ग्लोबल्स और स्थानीय लोगों को विलय करने का दृष्टिकोण गायब है (ए) बिल्टिन (मुझे कल्पना है कि यह जानबूझकर है, यानी आप बिल्टिन को "चर" के रूप में नहीं सोचते हैं ... लेकिन, यदि आप चुनते हैं तो वे हो सकते हैं ! -), और (बी) यदि आप नेस्टेड फ़ंक्शन में हैं, तो कोई भी चर जो स्थानीय कार्यों को संलग्न करने के लिए स्थानीय हैं (उन सभी के साथ एक नियम प्राप्त करने का कोई अच्छा तरीका नहीं है, साथ ही - केवल उन स्पष्ट रूप से उपयोग किए गए नेस्टेड फ़ंक्शन में, यानी "मुक्त चर", बंद होने में कोशिकाओं के रूप में जीवित रहते हैं, वैसे भी)।

मुझे लगता है कि ये समस्याएं आपके इच्छित उपयोग के लिए कोई बड़ा सौदा नहीं है, लेकिन आपने "कोने के मामलों" का उल्लेख किया है ;-)। यदि आपको उन्हें कवर करने की आवश्यकता है, तो अंतर्निहित कार्यों (यह आसान है) प्राप्त करने के तरीके हैं (सभी आसान नहीं हैं) (नामों को प्राप्त करने के लिए उन कार्यों को संलग्न करने से वेरिएबल जिन्हें आपने स्पष्ट रूप से नेस्टेड फ़ंक्शन में उल्लेख किया है - thefunction.func_code.co_freevars, thefunction.func_closure कोशिकाओं को प्राप्त करने के लिए, प्रत्येक सेल पर cell_contents अपना मूल्य प्राप्त करने के लिए)। (लेकिन, याद रखें, वे आपके घोंसले हुए फ़ंक्शन के कोड में स्पष्ट रूप से तक पहुंचने वाले कार्यों को संलग्न करने से भिन्न होंगे!)।

+0

अजीब है कि आप एक नेस्टेड फ़ंक्शन के अंदर से सभी चर नहीं प्राप्त कर सकते हैं। किसी को पता है कि क्यों 'स्थानीय() 'काम नहीं करेगा? ऐसा लगता है कि यह चाहिए! – sudo

7

क्या यह आपके इरादे से करता है?

d = dict(globals()) 
d.update(locals()) 

अगर मैं प्रलेखन सही ढंग से पढ़ा है, आप globals() dict की एक प्रतिलिपि बनाने, तो आप locals() dict (के बाद से locals(), वैसे भी अपने दायरे के भीतर वरीयता होनी चाहिए से किसी भी डुप्लिकेट और डालने नई प्रविष्टियां ऊपर लिख)।


मैं फ़ंक्शन कॉल के दायरे में चर का पूरा शब्दकोश वापस जाने के लिए एक उचित समारोह को प्राप्त करने में किसी भी भाग्य नहीं किया है।

from pprint import * 

def allvars_bad(): 
    fake_temp_var = 1 
    d = dict(globals()) 
    d.update(locals()) 
    return d 

def foo_bad(): 
    x = 5 
    return allvars_bad() 

def foo_good(): 
    x = 5 
    fake_temp_var = "good" 
    d = dict(globals()) 
    d.update(locals()) 
    return d 

pprint (foo_bad(), width=50) 
pprint (foo_good(), width=50) 

और आउटपुट:: यहाँ कोड है (मैं केवल इतना के लिए उत्पादन अच्छी तरह से स्वरूपित करने के लिए इस्तेमाल किया pprint)

{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'allvars_bad': <function allvars_bad at 0xb7d32b1c>, 
'd': <Recursion on dict with id=3084093748>, 
'fake_temp_var': 1, 
'foo_bad': <function foo_bad at 0xb7d329cc>, 
'foo_good': <function foo_good at 0xb7d32f0c>, 
'isreadable': <function isreadable at 0xb7d32c34>, 
'isrecursive': <function isrecursive at 0xb7d32c6c>, 
'pformat': <function pformat at 0xb7d32bc4>, 
'pprint': <function pprint at 0xb7d32b8c>, 
'saferepr': <function saferepr at 0xb7d32bfc>} 
{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'allvars_bad': <function allvars_bad at 0xb7d32b1c>, 
'd': <Recursion on dict with id=3084093884>, 
'fake_temp_var': 'good', 
'foo_bad': <function foo_bad at 0xb7d329cc>, 
'foo_good': <function foo_good at 0xb7d32f0c>, 
'isreadable': <function isreadable at 0xb7d32c34>, 
'isrecursive': <function isrecursive at 0xb7d32c6c>, 
'pformat': <function pformat at 0xb7d32bc4>, 
'pprint': <function pprint at 0xb7d32b8c>, 
'saferepr': <function saferepr at 0xb7d32bfc>, 
'x': 5} 

ध्यान दें कि दूसरे उत्पादन में, हम fake_temp_var ओवरराइट है, और एक्स है पेश; पहले आउटपुट में केवल allvars_bad के दायरे में स्थानीय वर्र्स शामिल थे।

तो यदि आप पूर्ण चरणीय दायरे तक पहुंचना चाहते हैं, तो आप स्थानीय कार्यों() को किसी अन्य फ़ंक्शन के अंदर नहीं डाल सकते हैं।


मैं वहाँ फ्रेम वस्तु के कुछ प्रकार था संदेह था, मैं सिर्फ नहीं (पता जहां तक) था कि यह देखने के लिए।

यह आपके कल्पना करने के लिए काम करता है, मेरा मानना ​​है कि:

def allvars_good(offset=0): 
    frame = sys._getframe(1+offset) 
    d = frame.f_globals 
    d.update(frame.f_locals) 
    return d 


def foo_good2(): 
    a = 1 
    b = 2 
    return allvars_good() 

->

{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d6474c>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'a': 1, 
'allvars_bad': <function allvars_bad at 0xb7d65b54>, 
'allvars_good': <function allvars_good at 0xb7d65a04>, 
'b': 2, 
'foo_bad': <function foo_bad at 0xb7d65f44>, 
'foo_good': <function foo_good at 0xb7d65f7c>, 
'foo_good2': <function foo_good2 at 0xb7d65fb4>, 
'isreadable': <function isreadable at 0xb7d65c6c>, 
'isrecursive': <function isrecursive at 0xb7d65ca4>, 
'pformat': <function pformat at 0xb7d65bfc>, 
'pprint': <function pprint at 0xb7d65bc4>, 
'saferepr': <function saferepr at 0xb7d65c34>, 
'sys': <module 'sys' (built-in)>} 
+0

अपने प्रश्न का उत्तर देने के लिए, मुझे नहीं पता :) यह वास्तव में मैं क्या खोजना चाहता हूं - चाहे दोनों को जोड़ना सही काम है। –

+0

हाँ, दुर्भाग्य से स्थानीय() को वहां होना चाहिए। ग्लोबल्स() के साथ समान - यह काम करने के लिए एक ही मॉड्यूल में होना चाहिए। मुझे आश्चर्य है कि कुछ sys._getframe() ट्रिकरी का उपयोग इसके बजाय किया जा सकता है। –

2

आप अपनी खुद की कर सकता है:

allvars = dict() 
allvars.update(globals()) 
allvars.update(locals()) 

या गठबंधन पहले दो लाइनों:

allvars = dict(globals()) 
allvars.update(locals()) 
1

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

globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    print "Vars: %d, %d, %d!" % (globalVar, paramVar, localVar) 

myfunc(123) 
+0

यह इंटरपोलेशन नहीं है। http://en.wikipedia.org/wiki/Variable_(computer_science)#Interpolation - पायथन में ऐसा नहीं है, लेकिन .format() फ़ंक्शन के साथ आप बहुत करीब आ सकते हैं। –

+0

और यदि आपको आश्चर्य है कि मैं% क्यों नापसंद करता हूं - इस तरह के बारे में सोचें: प्रिंट करें {{path}/myscript.py --input {path}/file1 --output {path}/file2 ".format (** स्थानीय ()) - "%" के साथ मुझे पथ को तीन बार पारित करने की आवश्यकता होगी। बहुत सारे चर के साथ यह बनाए रखने के लिए एक पूर्ण दुःस्वप्न बन जाता है। –

+0

@romkyns: ऐसा नहीं है। स्ट्रिंग '%' ऑपरेटर एक ** तर्क 'के रूप में' ** 'के साथ अनपैक करने की आवश्यकता के साथ एक dict तर्क ले सकता है: प्रिंट "% (पथ) s/myscript.py - इनपुट% (पथ) एस/file1 --output% (पथ) एस/file2 "% स्थानीय() –

2
globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    all_vars = locals.copy() 
    all_vars.update(globals()) 
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(all_vars) 

myfunc(123) 
संबंधित मुद्दे