2010-09-19 11 views
6

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

मैंने इसे कक्षा सजावट के रूप में संरचित किया है ताकि उस वर्ग के सभी उदाहरणों को उनके नाम दर्ज किए जाएंगे यदि ऐसा करना संभव हो। कोड काफी लंबा है इसलिए मैं इसे तब तक पोस्ट नहीं करूंगा जब तक कि पूछा न जाए। सामान्य तकनीक के रूप में निम्नानुसार हालांकि

  1. जो मैं चाहता

  2. caller = inspect.currentframe().f_back और खुले inspect.getframeinfo(caller).filename सेट और ast.parse के लिए भेज करने के लिए कोड के साथ वर्ग '__init__ विधि को सजाने के लिए है। मुझे यहां कोई त्रुटि नहीं है क्योंकि (1) यह केवल डिबगिंग/प्रोफाइलिंग/हैकिंग (2) के लिए है, यह सटीक प्रक्रिया 'बस' पूर्ण हो गई थी या कोड नहीं चल रहा था। क्या इसमें कोई समस्या है?

  3. ast.Assignment आवृत्ति का कारण बनता है वर्तमान में क्रियान्वित __init__ विधि

  4. चलाने के लिए len(assignment.targets) == 1 तो बाएं हाथ की ओर केवल एक आइटम है अगर मिल जाए, और मैं targets[0].id से बाहर नाम मिल सकता है। a = Foo() जैसे साधारण रूप में, assignment.valueast.Call का एक उदाहरण है। यदि यह एक शाब्दिक (उदा। सूची) है, तो value वह सूची और जमानत होगी क्योंकि जिस वस्तु में मुझे रूचि है वह किसी नाम पर असाइन नहीं किया जा रहा है।

क्या पुष्टि करते हैं कि assignment.value.func तथ्य उद्देश्य यह है कि मैं में दिलचस्पी रखता हूँ की type(obj).__call__ में है सबसे अच्छा तरीका है। मैं बहुत यकीन है कि मैं इसकी गारंटी रहा है कि यह "में वहाँ कहीं" कर रहा हूँ या कोड दौड़ भी नहीं होगा। मुझे बस शीर्ष स्तर पर होने की आवश्यकता है। करने के लिए स्पष्ट बात यह है कि यह चलें और सुनिश्चित करें कि इसमें कोई आंतरिक कॉल नहीं है। तब मुझे गारंटी है कि मेरे पास नाम है। (मेरा तर्क सही है, मुझे यकीन नहीं है कि इसकी धारणाएं हैं)। यह आदर्श नहीं है क्योंकि अगर मुझे Foo में दिलचस्पी है, तो इससे मुझे a = Foo(Bar()) को टॉस करने का कारण बन सकता है क्योंकि मुझे नहीं पता कि यह a = Bar(Foo()) है या नहीं।

बेशक मैं सिर्फ assignment.value.func.id जांच कर सकते हैं, लेकिन फिर किसी Foobar = Foo या कुछ और कर सकता था तो मैं यह भी भारी

किसी भी मदद पर भरोसा करने की बहुत सराहना की जाएगी नहीं करना चाहती। हमेशा के रूप में, मुझे किसी भी अन्य सुझाव या समस्याओं में दिलचस्पी है जो मैं देख सकता हूं।

इसके अलावा, मैं वास्तव में हैरान हूं कि मुझे केवल 'पायथन-इंटर्नल्स' टैग का आविष्कार करना पड़ा।

+0

+ कई - पायथन शांत है! – katrielalex

उत्तर

2

एएसटी आपको वह जवाब नहीं दे सकता है। Frame.f_lasti का उपयोग करके और फिर बाइटकोड में देखकर देखें। यदि अगली पंक्ति STORE_FAST नहीं है, तो आपके पास आंतरिक कॉल या कुछ और सरल असाइनमेंट के अलावा चल रहा है, जिसे आप ढूंढ रहे हैं।

def f(): 
    f = sys._getframe() 
    i = f.f_lasti + 3 # capture current point of execution, advance to expected store 
    print dis.disco(f.f_code, i) 
0

मैं कितनी मदद यह है के बारे में पता नहीं है, लेकिन आप locals() करने के लिए कॉल का उपयोग कर विचार किया है? यह dict देता है जिसमें सभी स्थानीय चर का नाम और मान होता है।

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

s = '' 
locals() 
>>> {'__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 's': '', '__name__': '__main__', '__doc__': None} 
t = s # I think this is what is of most importance to you 
locals() 
>>> {'__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 's': '', 't': '', '__name__': '__main__', '__doc__': None} 

तो तुम इस शब्दकोश पार और जाँच जो चर (उनके मूल्य के रूप में) हो सकता है प्रकार है कि आप देख रहे हैं की एक वस्तु।

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

+0

यह काम नहीं करता है क्योंकि 'स्थानीय()' हमेशा उस फ्रेम को संदर्भित करता है जिसे इसे बुलाया जाता है, मैं एक फ्रेम की तलाश में हूं। मैं 'inspect.currentfrmae' के लिए' sys._getframe() 'के साथ प्राप्त कर सकता हूं। समस्या यह है कि 'foo = bar() '_after_' bar .__ init __() 'रिटर्न तक' स्थानीय() '(उस असाइनमेंट फ्रेम को संदर्भित करता है) में एक प्रविष्टि नहीं बनाता है। लेकिन यह नाम पाने के लिए उचित जगह है क्योंकि मैं _every_ असाइनमेंट के बाद कोड डालने के बजाय इसे 'बार' पर सजावट के साथ कर सकता हूं। – aaronasterling

+0

@AaronMcSmooth: स्थानीय लोगों के बजाय ग्लोबल्स() को कॉल करने से इस समस्या को ठीक किया जा सकता है – inspectorG4dget

+1

@ InspectoG4det No इसी कारण से। 'ग्लोबल्स' बाहरीतम फ्रेम के लिए सिर्फ 'frame.f_locals' है और इसलिए प्रविष्टि' frame.f_locals' में नहीं है जब तक कि आंतरिक फ्रेम ('bar .__ init __()' इस मामले में) लौटाता है। – aaronasterling

0

मुझे यहां कोई त्रुटि नहीं है क्योंकि (1) यह सिर्फ डीबगिंग/प्रोफाइलिंग/हैकिंग (2) के लिए है, यह सटीक प्रक्रिया 'बस' पूरी हो गई थी या कोड नहीं चल रहा था। क्या इसमें कोई समस्या है?

हाँ:

  1. एक कार्यक्रम

  2. प्रतीक्षा इकाई शुरू

    यह

  3. foo.py संपादित

अब एक विशेष मॉड्यूल foo.py आयात करता है कोड जो एक पायथन में भरा हुआ है प्रक्रिया डिस्क पर पाए गए कोड से मेल नहीं खाती है।

फिर भी एक और कारण बाइटकोड को अलग करना एक बेहतर तकनीक हो सकता है।

0

यहां बताया गया है कि यह कैसे किया जाता है। अज्ञात सुराग देने वाला बहुत धन्यवाद। अपने alt खाते के लिए प्रतिनिधि रैक करने के लिए अपनी खोज में बहुत भाग्य।

import inspect 
import opcode 


def get_name(f): 
    """Gets the name that the return value of a function is 
    assigned to. 

    This could be modified for classes as well. This is a 
    basic version for illustration that only prints out 
    the assignment instead of trying to do anything with it. 
    A more flexible way would be to pass it a callback for when 
    it identified an assignment. 

    It does nothing for assignment to attributes. The solution 
    for that isn't much more complicated though. If the 
    instruction after the function call is a a `LOAD_GLOBAL`, 
    `LOAD_FAST` or `LOAD_DEREF`, then it should be followed by 
    a chain of `LOAD_ATTR`'s. The last one is the attribute 
    assigned to. 
    """ 

    def inner(*args, **kwargs): 
     name = None 

     frame = inspect.currentframe().f_back 
     i = frame.f_lasti + 3 

     # get the name if it exists 
     code = frame.f_code 
     instr = ord(code.co_code[i]) 
     arg = ord(code.co_code[i+1]) # no extended arg here. 
     if instr == opcode.opmap['STORE_FAST']: 
      name = code.co_varnames[arg] 
     elif instr in (opcode.opmap['STORE_GLOBAL'], 
         opcode.opmap['STORE_NAME']): 
      name = code.co_names[arg] 
     elif instr == opcode.opmap['STORE_DEREF']: 
      try: 
       name = code.co_cellvars[arg] 
      except IndexError: 
       name = code.co_freevars[arg - len(code.co_cellvars)] 
     ret = f(*args, **kwargs) 
     print opcode.opname[instr] 
     if name: 
      print "{0} = {1}".format(name, ret) 
     return ret 

    return inner 


@get_name 
def square(x): 
    return x**2 

def test_local(): 
    x = square(2) 

def test_deref(): 
    x = square(2) 
    def closure(): 
     y = x 
    return closure 

x = square(2) 
test_local() 
test_deref()() 

यह बहुत मुश्किल या तो list_[i] = foo() के लिए की कार्य यह पता लगाने की, frame.f_locals का उपयोग करके i के महत्व सहित नहीं होना चाहिए। मुश्किल लोग सचमुच होने जा रहे हैं और जब यह एक तर्क के रूप में पारित किया जाता है। उन दोनों मामलों को बहुत चुनौतीपूर्ण होना चाहिए।

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