هل من الممكن أن يكتب إلى كائن إطار الثعبان على النحو الذي عاد sys._getframe () من التعليمات البرمجية الثعبان تشغيل ضمن مترجم؟

StackOverflow https://stackoverflow.com/questions/626835

سؤال

وبالمناسبة من هذا السؤال ، هناك قليلا من السقالات داخل مترجم لتفقد الأشياء الإطار، والتي يمكن استردادها من قبل sys._getframe(). الكائنات إطار يبدو أن قراءة فقط، ولكن لا أستطيع أن أجد أي شيء واضح في المستندات التي تنص صراحة هذا. يمكن للشخص تأكيد ما إذا كانت هذه الكائنات للكتابة (بطريقة ما) أو قراءة فقط؟

import sys

def foobar():
    xx='foo'
    ff = sys._getframe()
    ff.f_locals['xx'] = 'bar'
    print xx

if __name__ == '__main__':
    foobar()

وهذا يطبع خارج 'foo "عند تشغيله ولكن آخر يوضح تحت قابل للكتابة كائن متغير عند تشغيله من الإطار الحالي في قذيفة التفاعلية.

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

المحلول

ومن مصدر سي بايثون، Objects/frameobject.c:

static PyMemberDef frame_memberlist[] = {
    {"f_back",      T_OBJECT,       OFF(f_back),    RO},
    {"f_code",      T_OBJECT,       OFF(f_code),    RO},
    {"f_builtins",  T_OBJECT,       OFF(f_builtins),RO},
    {"f_globals",   T_OBJECT,       OFF(f_globals), RO},
    {"f_lasti",     T_INT,          OFF(f_lasti),   RO},
    {"f_exc_type",  T_OBJECT,       OFF(f_exc_type)},
    {"f_exc_value", T_OBJECT,       OFF(f_exc_value)},
    {"f_exc_traceback", T_OBJECT,   OFF(f_exc_traceback)},
    {NULL}    /* Sentinel */
};
...
static PyGetSetDef frame_getsetlist[] = {
    {"f_locals",    (getter)frame_getlocals, NULL, NULL},
    {"f_lineno",    (getter)frame_getlineno,
                    (setter)frame_setlineno, NULL},
    {"f_trace",     (getter)frame_gettrace, (setter)frame_settrace, NULL},
    {"f_restricted",(getter)frame_getrestricted,NULL, NULL},
    {0}
};

لوPyMemberDef، أعلام RO أو READONLY يعني للقراءة فقط انها سمات. لPyGetSetDef، إذا كان لديه فقط جالبة، اقرأ فقط. وهذا يعني كل الصفات ولكن f_exc_type، f_exc_value، f_exc_traceback وf_trace للقراءة فقط بعد الخلق. وهذا مذكور أيضا في مستندات، تحت نموذج بيانات .

والكائنات التي أشار إليها سمات ليست بالضرورة للقراءة فقط. هل يمكن أن تفعل هذا:

>>> f = sys._getframe()
>>> f.f_locals['foo'] = 3
>>> foo
3
>>>

وعلى الرغم من أن هذا يعمل في مترجم، فإنه فشل وظائف في الداخل. ويستخدم المحرك تنفيذ مجموعة منفصلة للمتغيرات المحلية (f_fastlocals)، التي اندمجت في f_locals على الوصول، ولكن العكس ليس صحيحا.

>>> def foo():
...   x = 3
...   f = sys._getframe()
...   print f.f_locals['x']
...   x = 4
...   print f.f_locals['x']
...   d = f.f_locals
...   x = 5
...   print d['x']
...   f.f_locals
...   print d['x']
...
>>> foo()
3
4
4
5
>>>

في إطار عالمي، ويشير إلى f_local f_globals، الأمر الذي يجعل هذا العمل خدعة في مترجم. يعمل تعديل f_globals، ولكن يؤثر على وحدة كاملة.

نصائح أخرى

ووf_locals [ 'فو'] سبيل المثال عن طريق NXC يعمل لأن متاحة في نطاق وحدة. في هذه الحالة، f_locals هو f_globals، وf_globals على حد سواء للتعديل وتنعكس التعديلات في الوحدة النمطية.

وداخل نطاق وظيفة، والسكان المحليين () وf_locals وقابل للكتابة، ولكن "[التغييرات قد لا يؤثر على قيم المتغيرات المحلية المستخدمة من قبل المترجم]." 1 انها خيارا التنفيذ. في سي بايثون هناك بايت كود الأمثل للمتغيرات المحلية وLOAD_FAST. في بيثون، والمتغيرات المحلية (دائما تقريبا) مرة واحدة تعرف وظيفة يعرف، ويستخدم سي بايثون وبحث مؤشر للحصول على قيمة المتغير، بدلا من البحث القاموس.

في نظرية بحث القاموس يمكن أن الوكيل الذي الجدول، ولكن هذا الكثير من العمل لتحقيق مكاسب صغيرة.

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

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