2011-01-21 19 views
7

कहो में बाहरी गुंजाइश को एक्सेस करना, मैं चर के साथ कुछ गुंजाइश है, और एक समारोह इस दायरे में कहा जाता है कुछ अपरिवर्तनीय चर बदलना चाहता है:अजगर 2.6

 
def outer(): 
    s = 'qwerty' 
    n = 123 
    modify() 

def modify(): 
    s = 'abcd' 
    n = 456 

यह बाहरी गुंजाइश तक पहुँचने के लिए किसी भी तरह संभव है? Py3k से nonlocal चर जैसे कुछ।

निश्चित रूप से मैं इस मामले में s,n = modify(s,n) कर सकता हूं, लेकिन अगर मुझे कुछ सामान्य 'इंजेक्शन' की आवश्यकता होती है जो वहां निष्पादित होती है और मनमानी चरों को पुन: असाइन करने में सक्षम होनी चाहिए?

मेरे मन में प्रदर्शन है, इसलिए, यदि संभव हो, eval & स्टैक फ्रेम निरीक्षण का स्वागत नहीं कर रहा है :)


युपीडी: यह असंभव है। अवधि। हालांकि, बाहरी विकल्प में चर का उपयोग करने के कुछ विकल्प हैं:

  1. ग्लोबल्स का उपयोग करें। वैसे, func.__globals__ एक परिवर्तनशील शब्दकोश है;)
  2. एक dict/वर्ग उदाहरण में स्टोर चर/किसी अन्य परिवर्तनशील कंटेनर
  3. चर दें के रूप में तर्क & उन्हें एक टपल के रूप में वापस मिल: a,b,c = innerfunc(a,b,c)
  4. इंजेक्षन अन्य समारोह के बाईटकोड। यह byteplay पायथन मॉड्यूल के साथ संभव है।
+1

यह नहीं है कि स्कॉइंग कैसे काम करता है। आप एक अलग स्टैकफ्रेम पर एक दायरे तक पहुंचने के लिए कहते हैं। यह ** बहुत ** भ्रमित होगा यदि स्कोपिंग आप जो भी कोशिश करते हैं, उसे अनुमति देगी, पूंछ रिकर्सन को लूप में फिर से लिखने के बारे में सोचें। तो कोड अनुकूलन अचानक एक कार्यक्रम के अर्थ को बदल देगा, यह कभी नहीं होगा। – Tino

उत्तर

3

यह नहीं कैसे nonlocal काम करता है। यह गतिशील स्कोपिंग प्रदान नहीं करता है (जो केवल एक विशाल पिटा होने का इंतजार कर रहा है और आपकी औसत "बुराई" सुविधा से भी अधिक दुर्लभ रूप से उपयोगी है)। यह सिर्फ लेक्सिकल स्कोपिंग को ठीक करता है।

वैसे भी, आप जो कुछ भी ध्यान में रखते हैं वह नहीं कर सकते (और मैं कहूंगा कि यह एक अच्छी बात है)। यहां तक ​​कि एक गंदे लेकिन आसान हैक भी नहीं है (और जब हम इसमें हैं: ऐसे हैक्स निराश नहीं होते हैं क्योंकि वे आम तौर पर थोड़ा खराब करते हैं!)। बस इसके बारे में भूल जाओ और असली समस्या को ठीक से हल करें (आपने इसका नाम नहीं दिया है, इसलिए हम इस पर कुछ भी नहीं कह सकते हैं)।

निकटतम जो आप प्राप्त कर सकते हैं वह उस वस्तु को परिभाषित कर रहा है जो आप साझा करना चाहते हैं और इसे स्पष्ट रूप से पास करते हैं (उदाहरण के लिए कक्षा बनाएं और self का उपयोग करें, जैसा कि किसी अन्य उत्तर में सुझाया गया है)। लेकिन यह हर जगह करने के लिए अपेक्षाकृत बोझिल है, और अभी भी हैकर (हालांकि गतिशील स्कॉइंग से बेहतर है, क्योंकि "स्पष्ट रूप से स्पष्ट स्पष्ट है")।

7

कार्यों के बाहर चर को परिभाषित करें और global कीवर्ड का उपयोग करें।

s, n = "", 0 

def outer(): 
    global n, s 
    n = 123 
    s = 'qwerty' 
    modify() 

def modify(): 
    global n, s 
    s = 'abcd' 
    n = 456 
+1

इस काम के लिए 'xor' के साथ' और' को बदलें। अच्छी सलाह के लिए खरोंच से लिखना। – delnan

+0

@ डेलनान, मुझे खेद है, लेकिन ??? – orlp

+0

उनका मतलब है "उन्हें बाहर परिभाषित करें, या 'वैश्विक' का उपयोग करें, लेकिन दोनों नहीं"। – gotgenes

3

आपके विकल्प global चर,

s = None 
n = None 

def outer(self): 
    global s 
    global n 
    s = 'qwerty' 
    n = 123 
    modify() 

def modify(self): 
    global s 
    global n 
    s = 'abcd' 
    n = 456 

का उपयोग करें या विधियों के रूप में उन को परिभाषित करने और एक वर्ग या उदाहरण चर का उपयोग कर रहे हैं।

class Foo(object): 
    def __init__(self): 
     self.s = None 
     self.n = None 

    def outer(self): 
     self.s = 'qwerty' 
     self.n = 123 
     self.modify() 

    def modify(self): 
     self.s = 'abcd' 
     self.n = 456 
7

कभी-कभी मैं इस तरह के कोड में चलाता हूं।एक नेस्टेड समारोह बजाय एक nonlocal को बताए की एक परिवर्तनशील वस्तु को संशोधित करता है:

def outer(): 
    s = [4] 
    def inner(): 
     s[0] = 5 
    inner() 
+1

यह दिलचस्प है। बदसूरत, लेकिन दिलचस्प। – gotgenes

+1

'outer.s = 4' आदि –

+3

आप outer.s = 4 टाइप कर सकते हैं, लेकिन यह बाहरी() फ़ंक्शन में एक विशेषता असाइन करेगा। यह स्थानीय वैरिएबल को असाइन करने जैसा नहीं है। – joeforker

1

आप शायद भी ऐसा कर सकते हैं (यह नहीं कह यह सही है);

एक समारोह कि इतने

["a = qwerty","n = 123"] 

फिर दायरे में कर की तरह पंक्तियों के साथ एक सरणी देता है परिभाषित आप वार्स

for row in array: 
    eval(row) 

इस सुंदर रफ़ू hacky है, हालांकि की जरूरत है।

+0

मुझे लगता है कि आपका मतलब है 'exec (पंक्ति)'; eval केवल अभिव्यक्तियों के लिए है – Ord

संबंधित मुद्दे