سؤال

ركضت عبر هذه الحالة من UnboundLocalError في الآونة الأخيرة, والتي يبدو غريبا:

import pprint

def main():
    if 'pprint' in globals(): print 'pprint is in globals()'
    pprint.pprint('Spam')
    from pprint import pprint
    pprint('Eggs')

if __name__ == '__main__': main()

والتي تنتج:

pprint is in globals()
Traceback (most recent call last):
  File "weird.py", line 9, in <module>
    if __name__ == '__main__': main()
  File "weird.py", line 5, in main
    pprint.pprint('Spam')
UnboundLocalError: local variable 'pprint' referenced before assignment

pprint هو بوضوح لا بد في globals, و ستكون ملزمة في locals في البيان التالي.شخص ما يمكن أن نقدم تفسيرا لماذا ليس سعيدا حل pprint ربط في globals إلى هنا ؟

تحرير: شكرا على الردود الجيدة يمكنني توضيح سؤالي ذات الصلة المصطلحات:

في وقت الترجمة المعرف pprint تم وضع علامة المحلي إلى الإطار.لا تنفيذ نموذج لها أي تمييز حيث ضمن الإطار المحلي معرف غير ملزمة ؟ يمكن أن تقول "تشير إلى عالمية ملزمة حتى هذه بايت كود التعليمات ، وفي هذه المرحلة تم انتعاش المحلية ملزمة" أو تنفيذ نموذج لا حساب هذا ؟

هل كانت مفيدة؟

المحلول

يبدو أن الثعبان يرى from pprint import pprint خط وعلامات pprint كاسم المحلية إلى main() قبل تنفيذ أي رمز.منذ الثعبان يعتقد pprint يجب أن يكون متغير محلي ، الرجوع مع pprint.pprint() قبل "تعيين" مع from..import بيان ذلك يلقي هذا الخطأ.

هذا الشعور بقدر ما أنا يمكن أن تجعل من ذلك.

الأخلاقية, بالطبع, هو دائما وضع تلك import البيانات في الجزء العلوي من نطاق.

نصائح أخرى

أين المفاجأة ؟ أي متغير العالمية على نطاق أنك تعيين داخل هذا النطاق يتم وضع علامة المحلية إلى نطاق من قبل المترجم.

إذا الواردات سيكون التعامل معها بشكل مختلف ، أن سيكون من المستغرب imho.

قد جعل قضية عدم تسمية وحدات بعد الرموز المستخدمة فيه ، أو العكس ، على الرغم من.

حسنا, هذا كان مثيرا للاهتمام بما فيه الكفاية بالنسبة لي أن تجربة قليلا و قرأت من خلال http://docs.python.org/reference/executionmodel.html

ثم فعل بعض ترقيع مع التعليمات البرمجية الخاصة بك هنا وهناك ، وهذا هو ما يمكن أن تجد:

كود:

import pprint

def two():
    from pprint import pprint
    print globals()['pprint']
    pprint('Eggs')
    print globals()['pprint']

def main():
    if 'pprint' in globals():
        print 'pprint is in globals()'
    global  pprint
    print globals()['pprint']
    pprint.pprint('Spam')
    from pprint import pprint
    print globals()['pprint']
    pprint('Eggs')

def three():
    print globals()['pprint']
    pprint.pprint('Spam')

if __name__ == '__main__':
    two()
    print('\n')
    three()
    print('\n')
    main()

الإخراج:

<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Eggs'
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>

<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Spam'

pprint is in globals()
<module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>
'Spam'
<function pprint at 0xb7d596f4>
'Eggs'

في طريقة two() from pprint import pprint ولكن لا يلغي اسم pprint في globals, منذ global الكلمة الرئيسية لا تستخدم في نطاق two().

في طريقة three() إذ لا يوجد أي إعلان pprint اسم النطاق المحلي الافتراضي إلى اسم عالمي pprint الذي هو وحدة

في حين أنه في main(), في أول الكلمة global يستخدم لذلك جميع الإشارات إلى pprint في نطاق الأسلوب main() سوف أشير إلى global اسم pprint.والتي كما نرى هو وحدة في البداية و هو تنقضها في global namespace مع الأسلوب كما نفعل from pprint import pprint

على الرغم من أن هذا قد لا تكون الإجابة على السؤال على هذا النحو ، ولكن مع ذلك لها بعض الحقائق المثيرة للاهتمام أعتقد.

=====================

تحرير آخر الشيء المثير للاهتمام.

إذا كان لديك وحدة تقول:

mod1

from datetime import    datetime

def foo():
    print "bar"

و طريقة أخرى يقول:

mod2

import  datetime
from mod1 import *

if __name__ == '__main__':
    print datetime.datetime.now()

والتي للوهلة الأولى يبدو صحيحا لأن لديك المستوردة وحدة datetime في mod2.

الآن إذا حاولت تشغيل mod2 كبرنامج نصي وسوف رمي خطأ:

Traceback (most recent call last):
  File "mod2.py", line 5, in <module>
    print datetime.datetime.now()
AttributeError: type object 'datetime.datetime' has no attribute 'datetime'

لأن استيراد الثاني from mod2 import * وقد تنقضها اسم datetime في مساحة الاسم ، وبالتالي أول import datetime لم يعد صالحا.

الأخلاقية:وبالتالي ترتيب الواردات طبيعة الواردات (من x استيراد *) والوعي الواردات في استيراد وحدات - المسائل.

هذا السؤال تم الإجابة عليها قبل عدة أسابيع, ولكن أعتقد أنني يمكن توضيح الإجابات قليلا.أولا بعض الحقائق.

1:في بيثون ،

import foo

هو بالضبط تقريبا نفس

foo = __import__("foo", globals(), locals(), [], -1)

2:عند تنفيذ التعليمات البرمجية في وظيفة ، إذا كان الثعبان لقاءات متغير لم يتم تعريفها في وظيفة حتى الآن ، يبدو في النطاق العالمي.

3:الثعبان لديه الأمثل ويستخدم على وظائف يسمى "السكان المحليين".عندما الثعبان tokenizes وظيفة ، ومن يتتبع جميع المتغيرات التي قمت بتعيينها.فإنه يعين كل من هذه المتغيرات عدد من مفردة النغمة زيادة عدد صحيح.عندما بيثون يعمل وظيفة ، فإنه يخلق مجموعة مع العديد من فتحات كما أن هناك المتغيرات المحلية ، يعين كل فتحة القيمة الخاصة التي تعني "لم يتم تعيينه حتى الآن" ، حيث قيم هذه المتغيرات المخزنة.إذا كنت المرجعية المحلية التي لم يتم تعيينه حتى الآن ، بيثون يرى أن قيمة خاصة و يلقي UnboundLocalValue استثناء.

المسرح هو الآن.الخاص بك "من pprint استيراد pprint" هو في الحقيقة شكل من أشكال التنازل.لذلك الثعبان يخلق متغير محلي يسمى "pprint" التي تسبب انسداد العالمي المتغير.ثم عند الرجوع إلى "pprint.pprint" في الوظيفة ، يمكنك ضرب قيمة خاصة و الثعبان يطرح الاستثناء.إذا لم يكن لديك أن استيراد البيان في وظيفة ، بيثون استخدام نظرة طبيعية في السكان المحليين-أولا-ثم أنظر في جلوبل القرار وإيجاد pprint وحدة في جلوبل.

إلى إزالة الغموض هذا يمكنك استخدام "العالمية" الكلمة.الآن كنت قد عملت بالفعل الماضي مشكلتك وأنا لا أعرف ما إذا كنت حقا بحاجة إلى "العالمية" أو إذا كان بعض نهج آخر دعا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top