هل من الممكن أن يكتب إلى كائن إطار الثعبان على النحو الذي عاد sys._getframe () من التعليمات البرمجية الثعبان تشغيل ضمن مترجم؟
-
06-07-2019 - |
سؤال
وبالمناسبة من هذا السؤال ، هناك قليلا من السقالات داخل مترجم لتفقد الأشياء الإطار، والتي يمكن استردادها من قبل 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. في بيثون، والمتغيرات المحلية (دائما تقريبا) مرة واحدة تعرف وظيفة يعرف، ويستخدم سي بايثون وبحث مؤشر للحصول على قيمة المتغير، بدلا من البحث القاموس.
في نظرية بحث القاموس يمكن أن الوكيل الذي الجدول، ولكن هذا الكثير من العمل لتحقيق مكاسب صغيرة.
والاستثناءات ل"معروفة المتغيرات المحلية" هي إذا كان يستخدم الدالة على بيان إكسيك، وقضية إهمال من "وحدة من الواردات *". رمز بايت ولدت مختلفة، وأبطأ، لهذه الحالات.