Python �� Virtual Machine Code ��ǐՂ��邱�ƂŁApython �̌���d�l�E�����𑁂��^�I�m�ɗ����ł��邱�Ƃ� �悭����܂��B���̂��߂ɂ� �f�B�X�A�b�Z���u���[�Fdis ���W���[���� ����:inspect ���W���[�����L���ł��B�܂����� func_code �I�u�W�F�N�g�ɂ��R���p�C�����ʂ��l�܂��Ă���L�p�ł��B����� python �����̓�����[���������邽�߂� ceval.c �̃\�[�X�E�R�[�h��ǐՂł��邱�Ƃ��]�܂�܂��Bceval.c �� Virtual Machine Code �̊e���߂����s���Ă��镔��������ł��Bceval.c ��ǐՂ��邱�ƂŃ��[�J���ϐ��E�O���[�o���ϐ��̉������@�A�K�[�x�[�W�E�R���N�V�����̕��@�Apython �����Ŏ����� hash ���ʂ����Ă�������Ȃǂ�������悤�ɂȂ�܂��B
dis/inspce ���W���[�����g�����Ȃ�����Aceval.c ��ǐՂ����肷�邽�߂ɂ́Apython �C���^�[�v���^�[�������Ă����Ƃ��̑S�̂̊T�v�E���Ր}�𗝉����Ă����K�v������܂��B�O�̊�{�v�f�FCodeObject, FunctionObject, FrameObject �𗝉�����K�v������܂��BPython �C���^�[�v���^�[���O�̊�{�v�f�F�f�[�^�\���𒆐S�ɓ����Ă����l�q�𗝉�����K�v������܂��B
�{�e�ł� dis ���W���[�����g���� disassembler �̎g������������܂��B�u python virtual machine ���ǂ̂悤�ɓ����Ă���̂��v�upython virtual machine �̓����� inspect ������@�v�������܂��B���̉ߒ��ŎO�̊�{�v�f�FCodeObject, FunctionObject, FrameObject �𗝉����Ă����܂��B
�O�̊�{�v�f�𗝉��ł���ƁAceval.c C �\�[�X�E�R�[�h��ǐՂł���悤�ɂȂ�܂��Bceval.c �Ȃǂ�ǂ߂�悤�ɂȂ邱�ƂŁApython interpreter �̏ڍׂȓ������c���ł���悤�ɂȂ�܂��BReferecne Manual �����ł͐�������Ă��Ȃ��ڍׂ�����悤�ɂȂ�܂��B�܂� ceval.c �Ȃǂ� C �\�[�X������� python �ŏ����ׂ��� C �ŏ����ׂ����̖��m�ȃC���[�W�����Ă�悤�ɂȂ�܂��B
�㔼�ł� dis, inspect, func_code, C �\�[�X ��g�ݍ��킹�āApython interpreter �����̓�����ǐՂ��Ă����܂��B�Ō�� python �� decorator �\�����n�b�L���O���܂��B���� decorator �\�������� dis/inspect/func_code �̎��_���� python �R�[�h�̉�U�E�n�b�L���O���s���Ė��m�ɂ��܂��B
dis ���W���[���� python virtual machine code �̋t�A�b�Z���u���Fdisassemble ���s�����W���[���ł��B�W�����W���[���̒��ɂ���A�S�Ă� python �z�z�ɍŏ���������Ă��܂��Bdis.dis(.) ���ɂ��t�A�b�Z���u�����s�킹�܂��B
>python -m pydoc "dis.dis" dis.dis = dis(x=None) Disassemble classes, methods, functions, or code. With no argument, disassemble the last traceback.
dis.dis(.) �̈����ɂ͊���R�[�h�E�I�u�W�F�N�g�Ȃǂ��w�肵�܂��B���W���[����N���X�������ɂł���̂ł����A���̂Ƃ��͊��S�����t�A�b�Z���u�����Ă���邾���ł��B�c�O�ł����A���W���[�������̋t�A�b�Z���u���͂��Ă���܂���B���̂��߂ɂ́A��ŏq�ׂ� inspect ���W���[�����o�R����悤�ȍH���K�v�ƂȂ�܂��B
dis(.) ���̈����Ɋ�����^����A���̊��� python virtual machine code ��W���o�͂ɑł��o���Ă���܂��B
�u���b�N���s�{�e�ł́A���Ɏ����悤�� //@@ �� //@@@ �ň͂R�[�h�̋L�q�����x���g���܂��B����� //@@ �� //@@@ �ň͂����̕������ \#####.### �Ɩ��t�����t�@�C���ɂ��A//@@@ �̎��ɑ��� // �Ŏn�܂�s�̕�������R���\�[���E�R�}���h������Ƃ��Ď��s����Ƃ����Ӗ��ł��B���̗�ł� //@@ ���� //@@@ �͈̔͂̕������ \#####.### �t�@�C���ɂ��A���̃t�@�C�����J�����g�E�f�B���N�g���� a.cpp �ɃR�s�[���Aa.cpp �� cl.exe �ŃR���p�C�����鏈�����Ӗ����܂��B
//@@ �E �E //@@@ //copy \#####.### a.cpp //cl a.cpp -I.\�������̂悤�ȏ������G�f�B�^�Ŏ����I�ɍs���悤�ɂ��Ă��܂��Bwz �G�f�B�^�ł̃}�N���Ŏ������Ă��܂��Bctrl O + E �ŁA���̈�A�̏������s�킹�Ă��܂��BGPL �����Ō��J���Ă��܂��̂ŁAwz �G�f�B�^���g������͂����p��������
python �̂Ƃ��́A���s�I�v�V�������t���Ȃ����Ƃ��啔���Ȃ̂Łu //@@ ... //@@@ ������� copy \#####.### temp.py �� copy �����A�J�����g�E�f�B���N�g���� python.exe temp.py �����s������v���Ƃ܂ł� ctrl O + P �Ɋ���U�����G�f�B�^�E�}�N���ōs�킹�Ă��܂��Bsf �ł̃u���b�N�����v�Z������Ƃ��� �utemp.se ����� sf.exe @@temp.se �����s������v���Ƃ܂ł� ctrl O + S �Ɋ���U�����G�f�B�^�E�}�N���ōs�킹�Ă��܂��B
�ȉ��ł� //@@ �� //@@@ �ň͂v���O�����E�R�[�h�����x���o�Ă��܂����A���̂悤�ȈӖ��ł��邱�Ƃ��䏳�m���������B
�܂��͎�������Ă݂܂��傤�B
//@@ def testF(strAg="abc"): strAt = strAg+'xyz' print strAt import dis dis.dis(testF) //@@@ # dis.dis(testF) �o�� # �s�ԍ� byte�� �j���[���j�b�N �Q�ƕϐ�index ���߃o�C�g�E�R�[�h 2 0 LOAD_FAST 0 (strAg) # 7c 00 00 3 LOAD_CONST 1 ('xyz') # 64 01 00 6 BINARY_ADD # 17 7 STORE_FAST 1 (strAt) # 7d 01 00 3 10 LOAD_FAST 1 (strAt) # 7c 01 00 13 PRINT_ITEM # 4d 14 PRINT_NEWLINE # 4b 15 LOAD_CONST 0 (None) # 64 00 00 18 RETURN_VALUE # 6b
��� dis.dis(.) ���s��ŁA�u�s�ԍ�, byte ��, ���߁A�Q�ƕϐ�index�v�̎l�� dis.dis(testF) ���ł��o�������̂ł��B�ł��E�[�̖��߃o�C�g�E�R�[�h #... �͎�����Œlj��������̂ł��Bpython �v���O�����̏o�͂ł͂���܂���B���߃o�C�g�E�R�[�h�̏o�������͎��� kbplay.py... �̐߂���ь�� inspect ���W���[���̏��Ő������܂��B���̓R���p�C�������ƁA��̖��߃o�C�g�E�R�[�h����������܂��Bpython interpreter �́A���߃o�C�g�E�R�[�h����o�C�g���ǂݍ���ŁA�����������Ă����܂��Bdis.dis(.) �͖��߃o�C�g�E�R�[�h���j���[���j�b�N�ɒu�������Ă���킯�ł��B
�s�ԍ��̓\�[�X�s�ԍ����Ӗ����܂��Bbyte ���͖��߃o�C�g�E�R�[�h�̉��o�C�g�ڂ��������܂��B�j���[���j�b�N�́A���߃o�C�g�E�R�[�h�̈�o�C�g�ڂ�l�Ԃɕ���₷�� �@�\��\�� LOAD_FAST �Ȃǂ̕�����ɒu�����������̂ł��B
Assembler �o�͂̂悤�ɁA�j���[���j�b�N�ƈꏏ�� ��̓I�� hex byte code ���o�͂��Ă������ق����֗��Ȃ��Ƃ�����܂��B�ł� dis.dis(.) �� hex byte �R�[�h���o�͂��Ă���܂���Bdis ���W���[���ɏC���������� hex �R�[�h���o�͂����邱�Ƃ����݂܂������A���̃��W���[���Ƃ̗��ݍ����������āA���̔\�͂ł͖����ł����B
�ł� byteplay.py �Ƃ���������Ƃ��Ĉ����� dis assembler ���W���[�������J����Ă��܂��B����Ɏ�������� kbplay.py �����Ahex byte code �t���� disassmeble ���\�ɂ��܂����B���̂悤��import kbplay as bp; print bp.Code.from_code(?????.func_code).code �̍s�� ????? �̕����� disassemble �������������ɒu����������s��}�����邾���ŁAhex byte code �t�� disassmble ���ʂ��o�͂��܂��B
//@@ #07.06.26 def testF(): inAt = 3 print 1 + inAt print 2 import kbplay as bp; print bp.Code.from_code(testF.func_code).code //@@@ 3 1 64 01 00 LOAD_CONST 3 2 7d 00 00 STORE_FAST inAt 4 4 64 02 00 LOAD_CONST 1 5 7c 00 00 LOAD_FAST inAt 6 17 BINARY_ADD 7 47 PRINT_ITEM 8 48 PRINT_NEWLINE 5 10 64 03 00 LOAD_CONST 2 11 47 PRINT_ITEM 12 48 PRINT_NEWLINE 13 64 00 00 LOAD_CONST None 14 53 RETURN_VALUE
�����Ŋ��� func_code �I�u�W�F�N�g���g���Ă��܂��Bfunc_code �I�u�W�F�N�g�ɂ��ẮA�����̎��̐߂Ő������܂��B�Ƃ肠������ ????? �̕��������������邽�߂����� black box �s�Ǝv���Ă��������B
�������Akbplay.Code.from_code(.) �� func_code �I�u�W�F�N�g���������ɂł��܂���B�N���X�Ȃǂ������ɂł��܂���B���� disassemble �����ł��܂���Bdis.dis() �̂悤�ȏ_�������܂���B
�{�������� kbplay.py ���W���[����M��Afunc_code �ȊO�ł� disassmple �̑Ώۂɂł������ł��B�����g�́A�������܂苻�����Ȃ��̂Ŏ�Ԃ��|����C�ɂȂ�܂���B���̂悤�Ȍ��肳�ꂽ kbplay.py �ł����A�ŏ��̒i�K�ł͖𗧂Ǝv���܂��Bdis ���W���[���� kbplay(�܂��� byteplay) ��K�X�g�ݍ��킹�Ďg���Ă݂Ă��������B
���I�u�W�F�N�g�� code �I�u�W�F�N�g�������܂��B���� code �I�u�W�F�N�g�́A���I�u�W�F�N�g�� func_code �����Ƃ��� Python �v���O��������Q�Ƃł��܂��BCode �I�u�W�F�N�g�� co_varnames, co_names, co_consts �����������Ă��܂��Bco_varnames �^�v���̓��[�J���ϐ��������ێ����Ă��܂��Bco_names �^�v���̓O���[�o���ϐ����܂ϐ��������ێ����Ă��܂��Bco_consts �^�v���͒萔�ϐ��������ێ����Ă��܂��B�����̃^�v��������̓j���[���j�b�N�̃I�y�����h���l���߂�̂Ɏg���܂��B
Python virtual machine code �̃I�y�����h�ɂ́A���� co_varnames, co_names, co_consts �^�v���ւ̃C���f�b�N�X������܂��B���̂悤�ȋ�ł��B
//@@ def testF(inAg): global inGlb inAt = inAg + inGlb + 3 inGlb = 4 return inAg + inGlb import dis;dis.dis(testF) print "------------------" print "co_code: ", testF.func_code.co_code print "co_argcount:", testF.func_code.co_argcount print "co_consts: ", testF.func_code.co_consts print "co_varnames:", testF.func_code.co_varnames print "co_names: ", testF.func_code.co_names //@@@ 3 0 LOAD_FAST 0 (inAg) 3 LOAD_GLOBAL 1 (inGlb) 6 BINARY_ADD 7 LOAD_CONST 1 (3) 10 BINARY_ADD 11 STORE_FAST 1 (inAt) 4 14 LOAD_CONST 2 (4) 17 STORE_GLOBAL 1 (inGlb) 5 20 LOAD_FAST 0 (inAg) 23 LOAD_GLOBAL 1 (inGlb) 26 BINARY_ADD 27 RETURN_VALUE ------------------ co_code: | t d } d a | t S co_argcount: 1 co_consts: (None, 3, 4) co_varnames: ('inAg', 'inAt') co_names: ('inAg', 'inGlb', 'inAt')
co_varnames:('inAg', 'inAt') �^�v�������[�J���ϐ��̕�����^�v���ł��Bpython �ł͊��̈����ϐ������[�J���ϐ��Ɋ܂܂�܂��B�uLOAD_FAST i�v�̖��߃R�[�h�Ń��[�J���ϐ��� data stack �� push ���܂��BLOAD_FAST �̃I�y�����h�ɂ��� index i �� co_varnames �^�v���� i �Ԗڂ̗v�f�ł��邱�Ƃ��Ӗ����܂��Bco_varnames ������^�v���̓R���p�C�����ɒ�܂�܂��B
���� func_code �I�u�W�F�N�g�������Afunc_code �I�u�W�F�N�g�� co_code, co_argcount, co_consts, co_varnames, co_names �������܂��B
�� ������ func_code;�R�[�h�E�I�u�W�F�N�g �������� ���� co_code : ���� virtual machine code ���� co_argments : ���̈����̌� �f�t�H���g�����̐ݒ�ŕK�v�ɂȂ�܂� �� ���� co_consts[i] : ���l�╶����Ȃǂ̒萔�l�^�v�� ���� co_varnames[i] : ���[�J���ϐ���������̃^�v�� ���� co_names[i] : ���Ŏg���Ă���ϐ���������̃^�v�� ���� co_cellvars : �N���[�W���[�Ŏg����ϐ���������̃^�v�� ���� co_freevars : �N���[�W���[�Ŏg����ϐ���������̃^�v��
co_names:('inAg', 'inAt', 'inGlb') ���O���[�o���ϐ����܂�����^�v���ł��B�uLOAD_GLOBAL i�v�̖��߃R�[�h�ŁA�O���[�o���ϐ��� data stack �� push ���܂��BLOAD_GLOBAL �̃I�y�����h�ɂ��� index i �� co_names �^�v���� i �Ԗڂ̗v�f�ł��邱�Ƃ��Ӗ����܂��BPython compiler �́A global �錾���ꂽ�ϐ��� co_varnames �^�v���ɂ͓��ꂸ�� co_names �^�v���݂̂ɔz�u���܂��B������ global �ϐ��̓ǂݏ����ɂ� LOAD_GLOBAL/STORE_GLOBAL �R�[�h�����蓖�Ă܂��B
testF ���I�u�W�F�N�g�ɑ����� func_code �I�u�W�F�N�g�� python �R�[�h�̃R���p�C�����ɒ�܂�܂��Bco_varnames, co_names ���R���p�C�����ɒ�܂�܂��B��̃R�[�h��ł̓O���[�o���ϐ� inGlb �͉����ɂ����̂����݂��Ȃ��̂� testF() �������s�����Ƃ��G���[��O���������܂��B�ł����s�����ɃR���p�C�����邾���Ȃ� python �C���^�[�v���^�͓����Ă��܂��܂��B
�� testF(.) �ŁA�O���[�o���ϐ� inGlb ����̓I�Ɏw�������Ă��������߂�̂́A�� testF(.) ���܂��W���[�������s����Ƃ��ł��B������̎d�g�݂𗝉�����ɂ́A���ɏq�ׂ� python interpreter �̓������AFrameObject, eval.c �Ȃǂ̗������K�v�ł��B
Python ���͈ȉ��̂悤�� python interpreter �ɂ���Ď��s����܂��B
�������s����O�ɁA�����Ƃ� data stack �̈悪�݂����܂��BData stack �̈�ɂ́A������Ȃǃq�[�v�E�������[�̈�ɂ�����̂ւ̎Q�ƒl���ς܂�܂��B�ł����� data stack �� 1 ���[�h���Ƃɉ��炩�̃q�[�v�E�������ɂ���I�u�W�F�N�g�F���̂��w�����ƂɂȂ�܂��BPython virtual machine �� C ����Ƃ͈قȂ�A data stack �ɃI�u�W�F�N�g���̂�ςނ��Ƃ͂���܂���B�I�u�W�F�N�g�ւ̎Q�Ƃ݂̂�ς݂܂��B���̂悤�Ɂuprint 5�v���s�킹�� python code �� data stack �ɋl�܂��̂͐��l�I�u�W�F�N�g�̎Q�ƒl�z��̃C���f�b�N�X�ԍ� 1 �ɂ���Q�ƒl�ł��B���� 5 �̃I�u�W�F�N�g�̓q�[�v�̈�ɍ����̂ł���Adata stack �ɂ͍���܂���B
//@@ def testF(): print 5 inAt = 3 print inAt+5 import dis; dis.dis(testF) print "co_consts: ", testF.func_code.co_consts print "co_varnames:", testF.func_code.co_varnames //@@@ python temp.py 2 0 LOAD_CONST 1 (5) 3 PRINT_ITEM 4 PRINT_NEWLINE 3 5 LOAD_CONST 2 (3) 8 STORE_FAST 0 (inAt) 4 11 LOAD_FAST 0 (inAt) 14 LOAD_CONST 1 (5) 17 BINARY_ADD 18 PRINT_ITEM 19 PRINT_NEWLINE 20 LOAD_CONST 0 (None) 23 RETURN_VALUE co_consts: (None, 5, 3) co_varnames: ('inAt',)
Python Interpretor �͖��߃o�C�g�R�[�h���ꖽ�߂��Q�Ƃ��Ȃ���Adata stack �̈�ɎQ�ƒl��ς�(LOAD_FAST, LOAD_CONST)�A���Z����(BINARY_ADD)���{�������ʍ����q�[�v�̈���̂ւ̎Q�ƒl�� data_stack �� Top �̒l�ƒu��������Ƃ�������A�̏������J��Ԃ��܂��B
�q�[�v�̈�̃f�[�^�̎��̂ւ̎Q�ƂƁA���߃o�C�g�E�R�[�h�̃I�y�����h�Ƃ̑Ή��̓R���p�C�����ɒ�߂�� co_const[], co_varnames[] �Ȃǂ̔z��f�[�^�Ƃ��Ċ��I�u�W�F�N�g�̒��� CodeObject �ɍ\�z����܂��B
Python virtual machine �Ƃ̔�r�̂��߂ɔėp�I�� CPU �̍\�������Ɏ����܂��B�����ł� 32 bit CPU ���ƍl���Ă����܂��傤�BInternal bus �� 32 �r�b�g�E�T�C�Y�Ƃ��܂��傤�B
�ėp CPU �� ALU(Arithmetic Logic Unit) �𒆐S�ɁAprogram counter, instruction decoder, register ���z�u����A����炪�݂��� 32 bit internal bus �� bus switch ����Čq�����Ă��܂��B���߃R�[�h�ɉ����� ALU �ւ� bus switch ����ւ����܂��BALU �� and/or/add �Ȃǂ̉��Z�������s���܂��B���Z���ꂽ���ʂ� bus switch �� internal bus ���o�R���� register, stack RAM, data memory RAM �Ȃǂɕۑ�����܂��B
�ėp CPU �͉��̂悤�ɂ��� code memory �ɂ���v���O�����E�R�[�h�����s���Ă����܂�
�ėp CPU �ł́A2^32 �T�C�Y�� code memory �̈悩���̃R�[�h�����o���AALU �ŏ��������A���̌��ʂ� 2^32 �T�C�Y�� stack RAM �̈�A data memory RAM �̈�̈�ӏ��A�܂��̓��W�X�^�ɕۑ����܂��B���̂悤�� program counter �� stack pointer �Ȃǂ̃��W�X�^���������E�A�h���X��ێ��E�ω������邱�ƁA�܂� instruction decoder �� ALU �̓������ACMOS �g�����W�X�^��g�ݍ��킹���d�q��H�Ŏ����ł��܂��BC ����̊��L�q�́A���̔ėp CPU �̓��������������ŋL�q������̂ł��BC ����̊������s���邱�Ƃ� 2^32 �T�C�Y�� code momory �̈悩�� program code �����o����A���Z�����̌��ʂ� 2^32 �T�C�Y stack/data Memory RAM �̈�̓���̏ꏊ�ɕۑ�����܂��B
stack RAM �͈�{�ł���A�S�Ẵ��[�`���ŋ��p����܂��B��{�̋��ʃX�^�b�N�ɃI�[�g�ϐ���T�u�E���[�`������̖߂�A�h���X��ςݏグ�Ă����܂��B�T�u���[�`���̏������I������ return ���߂����s�����ƁA�X�^�b�N�E�|�C���^�E���W�X�^���Ăяo���O�̈ʒu�ɖ߂���܂��B Data Memory RAM �̈����ł���A�S�Ẵ��[�`���ŋ��p����܂��B
�_�C�i�~�b�N�ɐ�������Q�Ƃ����I�u�W�F�N�g�E�C���X�^���X�� malloc ���Ŋm�ۂ���� heap �̈�̈ꕔ�ɁA���̎��̂��m�ۂ��܂��BPython �� �Q�ƃJ�E���^���g���� garbage collection �@�\���g�ݍ��܂�Ă���Aheap �̈�̃I�u�W�F�N�g�E�C���X�^���X���ǂ�������Q�Ƃ���Ȃ��Ȃ�Ǝ����I�� heap �̈悩������Ă���܂��BC/C++ �Ȃǂ� garbege collection �@�\����������ł́A�C���X�^���X�̏��łɔ��� heap �̈�̉���������Ŗ����I�ɋL�q���܂��BC++ �ł� destructor �� delete �����g���܂��B
���ʂ� CPU ��Ŏ��s����� �}�V���E�R�[�h�ɔ�r���āAPython Virtual Machine �� ��蒊�ۉ�����Ă��܂��B�Ⴆ�� x86 �}�V���ł́A�R�[�h�E�Z�O�����g��̋��� code memory ��Ƀ}�V���E�R�[�h ������܂��B�f�[�^�E�Z�O�����g��̋��� stack/data RAM �̏�ɗl�X�̃f�[�^���悹�܂��B�ł� Python �ł� module, class, function �I�u�W�F�N�g����ɂ����āA���̒��� ���� code �� data stack ���݂����܂��B
���W���[�������s�����Ƃ��ɁA���W���[���� python virtual machine �R�[�h�����o����܂��B���̃��W���[����p�� data stack ������܂��Bdata stack ��� co_varnames[], co_names[], co_consts[] �o�R�ł̃I�u�W�F�N�g�E�C���X�^���X�ւ̎Q�Ƃ��ڂ����A�j���[���j�b�N�ɉ������������Ȃ���Ă����܂��B�N���X����̂Ƃ������l�ł��B
�ėp CPU �ɂ����� program counter �� stack pointer �̑���� FrameObject �� module, class function ���ꂼ�ꖈ�ɍ���܂��BFrameObject �� f_lasti �� program counter �ɑ������A�Ō�Ɏ��s�������߃R�[�h���w�������Ă��܂��Bf_stacktop �� stack pointer �ɑ������A�Ō�̖��߂����s������� stack �̍ŏ�i���w���Ă��܂��B
���� data stack �� FrameObject �͊��̌Ăяo�����ɐ��������̂ŁA�����Ƃɒ�܂����X�^�b�N�E�T�C�Y�����ł����Ă����� recursive call �����Ȃ����s�ł��܂��B�܂� generator ���̂悤�ȁA���̓r���ł̃R���e�L�X�g�E�X�C�b�`���ȒP�Ɏ����ł��܂��Bdis.dis(.) �� generator �������Ă��A���ʂ̊��̂Ƃ��Ɩw�Ǔ����R�[�h���g���Ă��邱�Ƃ�����܂��B
Python interpreter �ł� FrameObject ���S�̓���̗v�̖������ʂ��܂��B���� FrameObject �̒��g�� inspect module ���g���ēǂݏo���܂��B�ł� inspect ���W���[���̐����̑O�� python virtual machine �� C �R�[�h�����Ă����܂��傤�B�����ň����� PyFrameObject �Ɩw�Ǔ������̂� inspect ���W���[�����g���Ĕ`�����ނ���ł��B
Python Virtual Machine ���̂� C ����ŋL�q����Ă��܂��B���̃\�[�X�����J����Ă��܂��B�e machine �R�[�h�ɂ��� Language Reference �ɏ����Ă���ȏ�̂��Ƃ�m�肽���Ƃ��́Aceval.c �� ����Ɗ֘A���� c �\�[�X��ǂ܂˂Ȃ�܂���B ���� C source �̂��� FrameObject ��\���\���� PyFrameObject �ƁApython machie code �����s���� ceval.c �� python interpreter �̓����𗝉�����̂ɏd�v�ł��B
ceval.c �𒀎��ǂ��C���Ȃ��Ƃ��A�T�v�����ł��m���Ă����ƁApython interpreter �̓������C���[�W���₷���Ȃ�܂��B
�Ȃ� Python Reference Manual:�p�C�\���E���t�@�����X�E�}�j���A���� ceval.c �Ȃǂ� c source ���Q�Ƃ��Ȃ���ǂގ������Ǝ��͎咣���܂��BPython Reference Manual �����ł͉��������Ă���̂�������Ȃ����͂��������U��߂��Ă��܂��B
ceval.c �̓����ǂ��Ƃ��AFrameObject �\���̂̃f�[�^���ǂ̂悤�ɑ��삳��邩�����邱�ƂɂȂ�܂��Bceval.c �̓������ڍׂɒǐՂ��邽�߂ɂ́A�ŏ��ɉ��� PyFrameObject �\���̂𗝉����Ă����ׂ��ł��BPyFrameObject �̃C���X�^���X���Amodule/class/function/ ���ɐ݂����� FrameObject ������ł��B�܂� PyFrameObject �̒��̑����̃����o�[���A��ŏq�ׂ� inspect module ���g���� python ����Q�Ƃł��邩��ł��B�܂� PyFrameObject �\���̂� C �\�[�X�����Ɏ����܂��B
typedef struct _frame { PyObject_VAR_HEAD struct _frame *f_back; /* previous frame, or NULL */ PyCodeObject *f_code; /* code segment */ PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ PyObject *f_globals; /* global symbol table (PyDictObject) */ PyObject *f_locals; /* local symbol table (any mapping) */ PyObject **f_valuestack; /* points after the last local */ /* Next free slot in f_valuestack. Frame creation sets to f_valuestack. Frame evaluation usually NULLs it, but a frame that yields sets it to the current stack top. */ PyObject **f_stacktop; PyObject *f_trace; /* Trace function */ PyObject *f_exc_type, *f_exc_value, *f_exc_traceback; PyThreadState *f_tstate; int f_lasti; /* Last instruction if called */ /* As of 2.3 f_lineno is only valid when tracing is active (i.e. when f_trace is set) -- at other times use PyCode_Addr2Line instead. */ int f_lineno; /* Current line number */ int f_restricted; /* Flag set if restricted operations in this scope */ int f_iblock; /* index in f_blockstack */ PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */ int f_nlocals; /* number of locals */ int f_ncells; int f_nfreevars; int f_stacksize; /* size of value stack */ PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ } PyFrameObject;
��� int f_lasti �����o�[�����s���� machine code ���w���Ă��܂��Bint f_lineno ���\�[�X�s���w���Ă��܂��B�f�o�b�K�� f_lineno ��ǐՂ��Ă��܂��B
f_stacktop �����݂� stack �� Top �ʒu���w���Ă��܂��Bf_stacksize �̓��W���[��������g�� stack �T�C�Y��ێ����Ă��܂��B�R���p�C�����ɒ�܂�܂��B�Ȃ� python �ł͊��ďo���̓x�� data stack �������̂ŁA�����ɌŒ肳��Ă���X�^�b�N�E�T�C�Y�ł��A���J�[�V�u�Ȋ��Ăяo�����\�ł��BC ����ŕK�v���������ʂ���傫�ȃX�^�b�N�E��������K�v�Ƃ��܂���B
f_locals �͊������Ŏg�����[�J���ϐ��Ɗ������̔z��ł��B���߃o�C�g�FLOAD_FAST i �̃I�y�����h i �ƃI�u�W�F�N�g�Ƃ̑Ή��̓R���p�C�����ɒ�܂��Ă��܂��B�\�[�X���Ȃ��Ă��A�ϐ���������͕ێ�����Ă��܂��Bf_globals �̓��W���[���Œ�`����Ă���O���[�o���ϐ��̔z��ł��B���W���[���E�I�u�W�F�N�g����I�u�W�F�N�g���Ƃ� f_locals �� f_globals �ւ̎Q�Ɣz����܂��B������ inspect ���W���[�����g���ĎQ�Ƃł��܂��B
f_ncells, f_nfreevars �� closure ���������Ƃ��Ɏg���܂��B��͂� inspect ���W���[�����g���ĎQ�Ƃł��܂��B
f_back �́APyFrameObject �C���X�^���X���܂ފ����Ăяo�����A���̑��� PyFrameObject �C���X�^���X���w���Ă��܂��B��O�����������Ƃ��̊����߂������Ɏg���܂��B�܂� inspect ���W���[�����g�����ɂ́A�ԐړI�� f_back �ɂ����b�ɂȂ�܂��B
PyFrameObject �\���̂𗝉������ ceval.c �\�[�X��ǂ���悤�ɂ��Ȃ�܂��B
python interpreter �� Python Virtual Machine �R�[�h�����s����Ƃ� ceval.c �\�[�X�ɂ��� PyObject * PyEval_EvalFrame(PyFrameObject *f) �����Ăяo���܂��B������ PyFrameObject* ������ PyEval_EvalFrame(.) ���̈����ɗ^�����Ă��邱�Ƃɒ��ڂ��Ă��������BPyFrameObject �\���̂ւ̃|�C���^�������^�����Ă���APyFramObject �� PyObject **f_stacktop �����o�[���Adata stack ��ɐς܂ꂽ�f�[�^�����o���܂��B PyCodeObject *f_code �� int f_lasti ���APython Virtual Machine �R�[�h�� OP �R�[�h�����o���܂��B���� OP �R�[�h�� BUILD_LIST �̂Ƃ��́A���̕��������s���邱�ƂɂȂ�܂��B
PyObject * PyEval_EvalFrame(PyFrameObject *f) { �E �E first_instr = PyString_AS_STRING(co->co_code); next_instr = first_instr + f->f_lasti + 1; stack_pointer = f->f_stacktop; �E �E for (;;){ #define NEXTOP() (*next_instr++) opcode = NEXTOP(); switch (opcode) { �E �E case BUILD_LIST: �E �E } case ..........: �E �E } �E �E } }
PyEval_EvalFrame(.) ���� PyCodeObject *f_code ���w������ python virtual machine code �� return ���߂ɑ�������܂Ŏ��s�������܂��Bfor(;;){....} �̓�������葱���܂��B
BUILD_LIST �ɂ��āA���ڂ������Ă݂܂��傤�B�܂��͉��̂悤�� python ���X�g������R�[�h�����Ă݂܂��傤�B
//@@ def testF(): lstAt = [1,2,3] import dis;dis.dis(testF) //@@@ 2 0 LOAD_CONST 1 (1) 3 LOAD_CONST 2 (2) 6 LOAD_CONST 3 (3) 9 BUILD_LIST 3 12 STORE_FAST 0 (lstAt) 15 LOAD_CONST 0 (None) 18 RETURN_VALUE
BUILD_LIST virtual machine code �ɂ��X�^�b�N�ɐς�ł��� 1,2,3 �̒l���烊�X�g�E�I�u�W�F�N�g���� lstAt �̃��x���ϐ��ɎQ�ƒl�������Ă��܂��B
ceval.c �ɂ����� BUILD_LIST �̃R�[�h�͉��̂悤�ɂȂ��Ă��܂�
PyObject * PyEval_EvalFrame(PyFrameObject *f) { �E �E case BUILD_LIST: x = PyList_New(oparg); if (x != NULL) { for (; --oparg <= 0;) { w = POP(); PyList_SET_ITEM(x, oparg, w); } PUSH(x); continue; } break; �E �E } }
PyList_SET_ITEM(.) ���ɂ��Ă� Google Code Search ���g���āuPyList_SET_ITEM 2.4�v�Ō������Ă݂�Ɖ��̃R�[�h��������܂��BPython �̃��X�g�́AC ����̃\�[�X���猩��Δz��Ƃ����ׂ����ƕ�����܂��B
#define PyList_SET_ITEM(op, i, v) (((PyListObject *)(op))->ob_item[i] = (v))
inspect ���W���[���� python ������Ԃグ�Đl�Ԃɉ���₷���`�ŕ�����@�\��Z�߂����W���[���ł��B�������ȉ��ł� python code �ׂ邽�߂̋@�\�Ɍ��肵�Đ������܂��BFrameObject �o�R�Œ��ׂ���@�\�𒆐S�ɐ������Ă����܂�
���W���[�� �� �N���X�Ƃ����� Python interpreter �ŏ������s���I�u�W�F�N�g�ł́A�v���O�����̎��s�ɂ����� CodeObject, FramObject �̓�̃I�u�W�F�N�g����� �����Ă��܂��B �܂� python �ł͊����I�u�W�F�N�g�ł��B���R�Ɏ����^�тł��܂��BC ����ɂ����Ċ��|�C���^�ɍs��Ă����邱�Ƃ� python �ł��ł��Ă��܂��܂��B���̂��߂Ɋ��̐錾���� FunctionObject ������Ă��܂��B
�܂� inspect ���W���[�����g���Ƃ��A�܂� Python �̓����� C source �̃��x���ŗ������悤�Ƃ����Ƃ��A���� CodeObject, FramObject, FunctionObject �O�̃I�u�W�F�N�g���ڂ����������Ă����K�v������܂��B
�������������������������� Module/class ������������������������������������������������ ��FrameObject �� ��CodeObject �� �� f_code �� �� co_varname # ���[�J���ϐ������� �� f_builtins ���� �� �� co_names # �S���̕ϐ��������� �� f_globals ���� �� �� co_filename �� �� f_locals ���� �� ���R���p�C�����ɒ�܂� �� ��# stack �ƃ��[�J���ϐ��� �� �� �� f_localsplus �� �� �� �� �� �� �� �����W���[���� f_globals�� �� �� ���̒l�̈́����s���Ă����߄� �� �� �����Œ�܂� �� �� �� ���������������������������������������������������������������������������������������� �������������������������� Function ���������������������������������������������������� �� �� �� �� ��FrameObject �� FucntionObject ��CodeObject �� �� f_code �� func_code �� co_varname # ���[�J���ϐ������� �� f_builtins ���� �� func_globals �� co_names # �S���̕ϐ��������� �� f_globals ���� �� �� co_filename �� �� f_locals ���� �� ���̐錾���ɒ�܂� ���R���p�C�����ɒ�܂� �� ��# stack �ƃ��[�J���ϐ��� �� �� �� f_localsplus �� �� �� �����s�J�n���ɒ�܂� �� �� �� ����������������������������������������������������������������������������������������
FunctionObject �͊��݂̂ɍ���܂��B���̐錾���ɍ���܂��B���W���[����N���X�ɂ͈����ƈꏏ�ɌĂяo���Ƃ������Ƃ��Ȃ��̂āAFunctionObject ������܂���B
f_locals, func_globals, co_varnames �ȂǂɎ����@�\�̕ϐ������A���ꂩ�牽�x���o�Ă��܂��B�����̕ϐ����Őړ����� f_, func_, co_ �͉��̈Ӗ��������Ă��܂��B
������ f_ �� functiontion �̈Ӗ��Ɍ�����₷���̂ł����Aframe �̈Ӗ��ł��B������o���Ă����ƁAinspect �Ȃ� python �̒��g��`�����ނƂ��y�ɂȂ�܂��B
PyFrameObject �I�u�W�F�N�g���܂� caller's frame �z��S���� inspect ���W���[���� stack() �����g���Ē��ׂ��܂��B FrameObject �����̂悤�� f_back ����ă����N���ꂽ��Ԃ� python interpreter �������Ă��邩��ł��B
python -m pydoc inspect.stack Help on function stack in inspect: inspect.stack = stack(context=1) Return a list of records for the stack above the caller's frame.
��̓I�ɂ͉��̂悤�� inspect.stack() �����g���� FrameObject ���܂��X�g�̈ꗗ�� inspect �ł��܂��B
//@@ #07.05.24 inGl1 = 8 inGl2 = 9 def testF(): inAt = 3 inAt2 = 4 def innerF(): global inGl1, inGl2 inInAt = 5 print inAt + inGl1 + inGl2 + inAt2 + inInAt import pprint as pp;import inspect as ins;pp.pprint(ins.stack()) innerF() testF() //@@@ python temp.py 29 [(<frame object at 0x008FE6D8>, 'temp.py', 12, 'innerF', [' pp.pprint(ins.stack())\n'], 0), (<frame object at 0x00981840>, 'temp.py', 13, 'testF', [' innerF()\n'], 0), (<frame object at 0x008AE990>, 'temp.py', 14, '?', ['testF()\n'], 0)]
��̂悤�� inspect.stack() �ɂ��A�Ăяo�������� frame object, �t�@�C�����A�Ăяo���s�A�Ăяo�����������W���Ă���܂��B�f�o�b�K��Ń}�j���A�����삩�� import pprint as pp;import inspect as ins;pp.pprint(ins.stack()) �����s�����Ă��������ʂ��܂��B������g���� �ǂ�Ȍo�H�ŌĂяo���ꂽ���m�F�ł��܂��B�������{�e�ł̈�ԏd�v�ȏ��� frame object �ɂ���܂��BPyFrameObject ������Ă��邩��ł��B
inspect.getmembers(inspect.stack[i][0]) �ɂ���āAC �\�[�X:eval.c �ł��������� frame object�FPyFrameObject �̒��g�ׂ��܂��B���̂悤�ȋ�ł��B
//@@ #07.05.24 inGl1 = 8 inGl2 = 9 def testF(): inAt = 3 inAt2 = 4 def innerF(): global inGl1, inGl2 inInAt = 5 print inAt + inGl1 + inGl2 + inAt2 + inInAt #import pprint as pp;import inspect as ins;pp.pprint(ins.getmembers(ins.stack()[0][0]) ) import pprint as pp;import inspect as ins;print(ins.getmembers(ins.stack()[0][0]) ) innerF() testF() //@@@ python temp.py 29 [('__class__',), ('__delattr__', ), ('__doc__', None), ('__getattribute__', ), �E �E snip �E ('f_code', <code object innerF at 0091FC60, file "temp.py", line 7>), ('f_exc_traceback', None), ('f_exc_type', None), ('f_exc_value', None), ('f_globals', {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'inGl1': 8, 'inGl2': 9, 'testF': }), ('f_lasti', 74), ('f_lineno', 12), ('f_locals', {'inAt': 3, 'inAt2': 4, 'inInAt': 5, 'ins': , 'pp': }), ('f_restricted', 0), ('f_trace', None)]
frame object �� f_��lobals �����Ƀ��W���[���ɑ�����O���[�o���ϐ�������ƒl(��茵���ɂ͒l�ւ̎Q��)���L�^����Ă��܂��Bf_locals �����Ƀ��[�J���ϐ��̕�����ƒl(��茵���ɂ͒l�ւ̎Q��)���L�^����Ă��܂��B������ MAKE_FUNCTION, CALL_FUNCTION �ɂ���č���܂��B�����ŁA�R�[�h�E�I�u�W�F�N�g�� co_names[], co_varnames[] �͔z��ł���A f_globals/f_locals �͎����ł��邱�Ƃɒ��ӂ��ׂ��ł��BPython interpreter �� co_varnames[] ����ϐ�������������o���A��������Ƀ��[�J���ϐ��̃C���f�b�N�X���� data stack �Ƀ��[�J���ϐ���ݒ肵�Ȃ��� f_globals/f_locals �͎���������Ă����܂��B
�Ȃ� FrameObject �� f_locals �̃y�A�ɂȂ��Ă��鉺�̎����� pprint ���g���ăL�[�̃A���t�@�x�b�g���ŏo�͂����Ă��܂��Bco_varnames[] ���X�g�̎��Ƃ͈قȂ� f_locals �����̃L�[�̏����ɂ́A���ɈӖ��͂���܂���Bceval.c �̃\�[�X��ǂ��Ă� f_locals ���g���̂� NULL �Ɣ�r���ă��[�J���ϐ��̗L�������Ă��邾���ł��B
('f_locals', {'inAt': 3, 'inAt2': 4, 'inInAt': 5, 'ins':, 'pp': }),
f_globals ���������l�ɁA�L�[�̏����ɂ͈Ӗ��͂���܂���B
������d�v�Ȃ̂� FrameObject f_code �����ł��B���̂悤�ɁA���� f_code ������ inspect �ł��邩��ł��B������g���A���܂ł̐����ł͌��邱�Ƃ��ł��Ȃ��������W���[����N���X�� python virtual machine code �����邱�Ƃ��ł��邩��ł��Bdis.dis(.) �ł͖����������A���W���[����N���X�� byte code �� FrameObject.f_code ���猩�邱�Ƃ��ł��邩��ł��B�e���߂� hex �l������邩��ł��B
//@@ #07.05.24 inGl1 = 8 inGl2 = 9 def testF(): inAt = 3 inAt2 = 4 def innerF(): global inGl1, inGl2 inInAt = 5 print inAt + inGl1 + inGl2 + inAt2 + inInAt import pprint as pp;import inspect as ins;pp.pprint(ins.getmembers(ins.stack()[0][0].f_code) ) innerF() testF() //@@@ [('__class__',), ('__cmp__', ), ('__delattr__', ), ('__doc__', �E �E snip �E ('co_argcount', 0), ('co_cellvars', ()), ('co_code', 'd\x01\x00}\x02\x00\x88\x00\x00t\x02\x00\x17t\x03\x00\x17\x88\x01\x00\x17|\x02 \x00\x17GHd\x00\x00k\x05\x00}\x00\x00d\x00\x00k\x07\x00}\x01\x00|\x00\x00i\x05 \x00|\x01\x00i\t\x00|\x01\x00i\n\x00\x83\x00\x00d\x02\x00\x19d\x02\x00\x19i\x0b \x00\x83\x01\x00\x83\x01\x00\x01d\x00\x00S'), ('co_consts', (None, 5, 0)), ('co_filename', 'temp.py'), ('co_firstlineno', 7), ('co_flags', 3), ('co_freevars', ('inAt', 'inAt2')), ('co_lnotab', '\x00\x01\x00\x01\x06\x01\x15\x02'), ('co_name', 'innerF'), ('co_names', ('inInAt', 'inAt', 'inGl1', 'inGl2', 'inAt2', 'pprint', 'pp', 'inspect', 'ins', 'getmembers', 'stack', 'f_code')), ('co_nlocals', 3), ('co_stacksize', 4), ('co_varnames', ('pp', 'ins', 'inInAt'))]
���̕����� python virtula machine �̋�̓I�ȃo�C�g�E�R�[�h�̒l�̗�ł��B
('co_code', 'd\x01\x00}\x02\x00\x88\x00\x00t\x02\x00\x17t\x03\x00\x17\x88\x01\x00\x17|\x02 \x00\x17GHd\x00\x00k\x05\x00}\x00\x00d\x00\x00k\x07\x00}\x01\x00|\x00\x00i\x05 \x00|\x01\x00i\t\x00|\x01\x00i\n\x00\x83\x00\x00d\x02\x00\x19d\x02\x00\x19i\x0b \x00\x83\x01\x00\x83\x01\x00\x01d\x00\x00S'),
��ł� 'd' == 0x64 �Ȃ� ASCII �����ŕ\����R�[�h�� '\x..' hex �\���ł͂Ȃ� ASCII �������g���ĕ\�����Ă��܂��B���̂悤�ɂ��Ă��A���߃o�C�g�E�R�[�h�Ff_code.co_code ���������܂܂Ȃ� hex ���l�ŕ\���ł��܂��B
//@@ import inspect as ins import sys for i, x in enumerate(ins.stack()[0][0].f_code.co_code): strAt = hex(ord(x)) if (i%10==0): print if len(strAt) == 3: print "0x0" + strAt[-1], else: print strAt, #print #print [hex(ord(x)) for x in ins.stack()[0][0].f_code.co_code] //@@@ 0x64 0x00 0x00 0x6b 0x00 0x00 0x5a 0x01 0x00 0x64 0x00 0x00 0x6b 0x02 0x00 0x5a 0x02 0x00 0x78 0x7d 0x00 0x65 0x03 0x00 0x65 0x01 0x00 0x69 0x04 0x00 0x83 0x00 0x00 0x64 0x01 0x00 0x19 0x64 0x01 0x00 0x19 0x69 0x05 0x00 0x69 0x06 0x00 0x83 0x01 0x00 0x44 0x5d 0x5b 0x00 0x5c 0x02 0x00 0x5a 0x07 0x00 0x5a 0x08 0x00 0x65 0x09 0x00 0x65 0x0a 0x00 0x65 0x08 0x00 0x83 0x01 0x00 0x83 0x01 0x00 0x5a 0x0b 0x00 0x65 0x07 0x00 0x64 0x02 0x00 0x16 0x64 0x01 0x00 0x6a 0x02 0x00 0x6f 0x05 0x00 0x01 0x48 0x6e 0x01 0x00 0x01 0x65 0x0c 0x00 0x65 0x0b 0x00 0x83 0x01 0x00 0x64 0x03 0x00 0x6a 0x02 0x00 0x6f 0x10 0x00 0x01 0x64 0x04 0x00 0x65 0x0b 0x00 0x64 0x05 0x00 0x19 0x17 0x47 0x71 0x33 0x00 0x01 0x65 0x0b 0x00 0x47 0x71 0x33 0x00 0x57 0x64 0x00 0x00 0x53
���ł͂Ȃ����W���[���� virtual machine code ���������Ƃ�������܂��B�ł����̂Ƃ��̂悤�ɒP���ɂ͌����܂���Bdis.dis(module) �Ƃ���Ă��A������ disassemble ���Ă���܂���B���W���[���� import ������ł́A���W���[���� code �I�u�W�F�N�g�͎̂Ă��Ă��܂�����ł��B�p�ς݂ɂȂ��Ă��܂�����ł��B
�ł� inspect.stack()[0,0].f_code �ƁAFrameObject ����A���s���̃t���[���� code object �����o���܂��B������t�A�b�Z���u�����邱�ƂŁA���܂ł̐����ł͂ł��Ȃ��������W���[���̋t�A�b�Z���u�����\�ɂȂ�܂��B
//@@ #07.05.24 inGlb = 8 def testF(): global inClb inAt = 3 print inAt + inGlb testF() import dis;import inspect as ins;dis.dis(ins.stack()[0][0].f_code) //@@@ python temp.py 11 2 0 LOAD_CONST 0 (8) 3 STORE_NAME 0 (inGlb) 3 6 LOAD_CONST 1 (<code object testF at 0091FC20, file "temp.py", line 3>) 9 MAKE_FUNCTION 0 12 STORE_NAME 1 (testF) 8 15 LOAD_NAME 1 (testF) 18 CALL_FUNCTION 0 21 POP_TOP �Esnip �E
���̂悤�� FrameObject stack �� f_code �o�R�Ń��W���[���� co_varnames[], co_names[], co_consts[] ��������悤�ɂȂ�܂��B
//@@ #07.05.24 inGlb = 8 def testF(): global inClb inAt = 3 print inAt + inGlb testF() import inspect as ins;print(ins.stack()[0][0].f_code.co_varnames) import inspect as ins;print(ins.stack()[0][0].f_code.co_names) import inspect as ins;print(ins.stack()[0][0].f_code.co_consts) //@@@ python temp.py 11 ('inGlb', 'ins', 'testF') ('inGlb', 'testF', 'inspect', 'ins', 'stack', 'f_code', 'co_varnames', 'co_names', 'co_consts') (8, <code object testF at 0091FC20, file "temp.py", line 3>, None, 0)
���W���[���̋t�A�b�Z���u�������������Ƃ��AFramObject.f_code �o�R�ł͂Ȃ� __bultin__.compile(.) �����g�����@������܂��B
>type temp2.py inGl = 5 def testF(inAg): inAg = 3 inAg+=inGl return inAg testF(4)
��̂悤�Ƀ��W���[�� temp2.py �t�@�C���� python �R�[�h����������ł����A���� python �R�[�h�����s����A�ꉞ virtual machine code �����邱�Ƃ��ł��܂��B�ł� temp2.py �t�@�C���� python source ��������R���p�C��������ɋt�A�b�Z���u�����Ă���A�ʓ|�ł��B
//@@ f = open('temp2.py', 'U') codestring = f.read() f.close() codeobject = __builtins__.compile(codestring, 'temp2','exec') import dis dis.dis(codeobject) //@@@ 1 0 LOAD_CONST 0 (5) 3 STORE_NAME 0 (inGl) 2 6 LOAD_CONST 1 (<code object testF at 0091FCA0, file "temp2", line 2>) 9 MAKE_FUNCTION 0 12 STORE_NAME 1 (testF) 7 15 LOAD_NAME 1 (testF) 18 LOAD_CONST 2 (4) 21 CALL_FUNCTION 1 24 POP_TOP 25 LOAD_CONST 3 (None) 28 RETURN_VALUE
�Ȃɂ��Atemp2.py �̂悤�ȕʃt�@�C���Ɉ�U�����o���̂��ʓ|�ł��B�ł� inspect �̂Ƃ��̂悤�ɁAdisassemble �̂��߂̗]���ȃR�[�h������Ȃ��̂������b�g�ł��Bimport pprint as pp �Ȃǂ�lj�����ƁA���[�J���ϐ��������Ă��܂��܂��B���W���[���� machine code ���ς���Ă��܂��܂��B
�ł� FrameObject.f_code �o�R�ł��A���̂悤�� dis() ���������ŏ����Ă�邱�ƂŁA���W���[�������t�A�b�Z���u�����邱�Ƃ��ł��܂��B��������A���W���[�����ւ̉e�������Ȃ��ł��܂��B
//@@ def dis(): import dis;import inspect as ins;dis.dis(ins.stack()[1][0].f_code) inAt = 3 print inAt dis() //@@@
�����g�͏�� dis() ����������p�̃��W���[�� kcommon.py �̒��ɂɏ����Ă���܂��B��������̂悤�Ɏg���Ă��܂��B
//@@ inAt = 3 print inAt import kcommon as kc;kc.dis() //@@@ 3 1 0 LOAD_CONST 0 (3) 3 STORE_NAME 0 (inAt) 2 6 LOAD_NAME 0 (inAt) 9 PRINT_ITEM 10 PRINT_NEWLINE �Esnip �E
�ǂ���g���ă��W���[����N���X�̃f�B�X�E�A�b�Z���u�����邩�͓K�X���f�肢�܂��B
inspect.getmebers(.) �͈����I�u�W�F�N�g�̃����o�[�������W�߂��ĕ�����@�\�ł�����A�N���X�ɂ��g���܂��B���̂悤�ȋ�ł��B
//@@ class ClTest: m_inStt=5 def __init__(self): self.m_in = 3 clAt = ClTest() import inspect as ins;import pprint as pp;pp.pprint( ins.getmembers(clAt) ) print "----------------" import inspect as ins;import pprint as pp;pp.pprint( ins.getmembers(ClTest) ) //@@@ C:\my\vc7\mtCm>python temp.py [('__doc__', None), ('__init__',>), ('__module__', '__main__'), ('m_in', 3), ('m_inStt', 5)] ---------------- [('__doc__', None), ('__init__', ), ('__module__', '__main__'), ('m_inStt', 5)]
���x�� object ���p��������A���Ȃ킿 new style class �� inspect.getmembers(.) ��K�p���Ă݂܂��傤�B
//@@ class ClTest(object): m_inStt=5 def __init__(self): self.m_in = 3 clAt = ClTest() import inspect as ins;import pprint as pp;pp.pprint( ins.getmembers(clAt) ) print "----------------" import inspect as ins;import pprint as pp;pp.pprint( ins.getmembers(ClTest) ) //@@@ C:\my\vc7\mtCm>python temp.py [('__class__',), ('__delattr__', ), ('__dict__', {'m_in': 3}), ('__doc__', None), ('__getattribute__', ), ('__hash__', ), ('__init__', >), ('__module__', '__main__'), ('__new__', ), ('__reduce__', ), ('__reduce_ex__', ), ('__repr__', ), ('__setattr__', ), ('__str__', ), ('__weakref__', None), ('m_in', 3), ('m_inStt', 5)] ---------------- [('__class__', ), ('__delattr__', ), ('__dict__', ), ('__doc__', None), ('__getattribute__', ), ('__hash__', ), ('__init__', ), ('__module__', '__main__'), ('__new__', ), ('__reduce__', ), ('__reduce_ex__', ), ('__repr__', ), ('__setattr__', ), ('__str__', ), ('__weakref__', ), ('m_inStt', 5)]
dis, inspect ���W���[���Ɋւ��āA�����悭�g�� python ��s�R�[�h�����ɂ܂Ƃ߂Ă����܂��BPython virtual machine ����������Ă���̂��`�����݂����Ƃ��ɁA�����̍s�� python source �ɑ}�����Ă��܂��B���܂ł̐����ŁA�e�R�[�h�̈Ӗ��͕���Ǝv���܂��B���� testF �Ȃǂ̃p�����[�^��K�X�C�����Ă����p���������B
import dis; dis.dis(testF) import kcommon as kc; kd.dis() print testF.func_globals print testF.func_code.co_names import pprint as pp;pp.pprint(testF.func_globals ) import inspect as ins;import pprint as pp;pp.pprint(ins.getmembers(testF)) import inspect as ins;print dict(ins.getmembers(testF.func_code))['co_names'] import inspect as ins; print(ins.stack()[0][0].f_globals ) import inspect as ins; print(ins.stack()[0][0].f_globals ) import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_globals ) import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_locals ) import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_builtins ) import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_code.co_names ) import inspect as ins; import dis;dis.dis(ins.stack()[0][0].f_code) import inspect as ins;import pprint as pp;pp.pprint( ins.getmembers(testF.func_code) ) import inspect as ins;import pprint as pp;pp.pprint( ins.getmembers(ClTest) ) import inspect as ins;import pprint as pp;pp.pprint( ins.getmembers(ins.stack()[0][0]) )
���܂Ő������Ă��� dis ���W���[��, func_code �I�u�W�F�N�g�Aceval.c, inspect ���W���[�����g���� python �������ōs���Ă��鏈���̗l�q�������ɔ`������ł݂܂��傤�B�I�[�v���� python �͌��悤�Ǝv���A�ǂ��܂łł��`�����܂��Ă���܂��B
�܂��͎�n�߂ɁA�ł��P���ȗ�Ƃ��� python virtual machine code �ɂ��ϐ��̓���ւ������Ă݂܂��傤�Bpython �ł� x,y = y,x �� x,z,y = z,y,z �Ƃ��������ŕϐ��̓���ւ����s���܂��B������R���p�C���͂ǂ̂悤�ɍs���Ă���̂ł��傤���Bpython virtual machine code �����Ă݂܂��傤�B
//@@ x,y = (1,2) x,y = y,x print (x,y) import kcommon as kc; kc.dis() //@@@ (2, 1) 1 0 LOAD_CONST 3 ((1, 2)) 3 UNPACK_SEQUENCE 2 6 STORE_NAME 0 (x) 9 STORE_NAME 1 (y) 2 12 LOAD_NAME 1 (y) 15 LOAD_NAME 0 (x) 18 ROT_TWO 19 STORE_NAME 0 (x) 22 STORE_NAME 1 (y) 3 25 LOAD_NAME 0 (x) 28 LOAD_NAME 1 (y) 31 BUILD_TUPLE 2 34 PRINT_ITEM 35 PRINT_NEWLINE
x,y = y,x �̂悤�ȓ�̕ϐ��̓���ւ��� ROT_TWO ���߂��g���� data stack ��̏�ʓ�̕ϐ��Q�ƒl�����ւ��Ă��邾���ł����B���̋[���R�[�h�̂悤�� buffer �ϐ� tempAt ����݂�����悤�ɐ^���͂��Ă��܂���ł����B�R���p�C���Ɍ����I�ȃR�[�h�����������Ă���w�͂��f���܂��B
tempAt = x x = y y = tempAt
x,z,y = z,y,z �̂悤�ɕ����̕ϐ��̓���ւ����͂ǂ�����Ă���̂ł��傤���B
//@@ x,y,z = (1,2,3) x,z,y = z,y,x print (x,y,z) import kcommon as kc; kc.dis() //@@@ python temp.py (3, 1, 2) 1 0 LOAD_CONST 4 ((1, 2, 3)) 3 UNPACK_SEQUENCE 3 6 STORE_NAME 0 (x) 9 STORE_NAME 1 (y) 12 STORE_NAME 2 (z) 2 15 LOAD_NAME 2 (z) 18 LOAD_NAME 1 (y) 21 LOAD_NAME 0 (x) 24 ROT_THREE 25 ROT_TWO 26 STORE_NAME 0 (x) 29 STORE_NAME 2 (z) 32 STORE_NAME 1 (y) 3 35 LOAD_NAME 0 (x) 38 LOAD_NAME 1 (y) 41 LOAD_NAME 2 (z) 44 BUILD_TUPLE 3 47 PRINT_ITEM 48 PRINT_NEWLINE
����ǂ� ROT_THREE �� ROT_TWO �� data stack ��̃f�[�^�̓�̉�]�����g�ݍ��킹�� x,z,y = z,y,x ���������Ă��܂����B����ւ��������]����Ŏ������Ă���Ƃ͈ȊO�ł����B�R���p�C���œ���ւ���Ԃ肵 ROT_TWO �Ȃǂ̉�]����̑g�ݍ��킹�ɂ��Ă�����Ȃ�Ďv�������܂���ł����B
�������ݍ���ŁA��{�ƂȂ� PyObject �����Ă����܂��B Python �ł͑S�Ă��I�u�W�F�N�g�Ƃ��Ĉ����܂��BC source code ���ł� PyObject* �Ƃ��Ĉ����܂��BC source �ł� PyObject �͉��̂悤�ɒ�`����Ă��܂��B
/* PyObject_HEAD defines the initial segment of every PyObject. */ #define PyObject_HEAD \ _PyObject_HEAD_EXTRA \ # ��f�o�b�O���͋� int ob_refcnt; \ struct _typeobject *ob_type; /* Nothing is actually declared to be a PyObject, but every pointer to * a Python object can be cast to a PyObject*. This is inheritance built * by hand. Similarly every pointer to a variable-size Python object can, * in addition, be cast to PyVarObject*. */ typedef struct _object { PyObject_HEAD } PyObject;
�v�� Python �̃I�u�W�F�N�g�Ƃ́u���t�@�����X�E�J�E���g�Fob_refcnt�v�Ɓu�^�C�v�Fob_type�v���ŏ��̕����ɔ������\���̂��Ƃ������Ƃł��B�Ⴆ�Ύ����I�u�W�F�N�g�͉��̂悤�ɒ�`����Ă��܂��B
typedef struct _dictobject PyDictObject; struct _dictobject { PyObject_HEAD int ma_fill; /* # Active + # Dummy */ int ma_used; /* # Active */ /* The table contains ma_mask + 1 slots, and that's a power of 2. * We store the mask instead of the size because the mask is more * frequently needed. */ int ma_mask; /* ma_table points to ma_smalltable for small tables, else to * additional malloc'ed memory. ma_table is never NULL! This rule * saves repeated runtime null-tests in the workhorse getitem and * setitem calls. */ # �������Ƃ��� ma_smalltable # �v�f����������ƁA�ʂɗ̈���m�ۂ��� PyDictEntry *ma_table; # lookdict(.) or lookdict_string(.) PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash); PyDictEntry ma_smalltable[PyDict_MINSIZE]; };
�����E���X�g�E�^�v���E���Ȃ�ł����Ă��A �ŏ��̕����� PyObjectHead ������̂ŁAC souce code ���� PyObject* ���g���� cast �ł��܂��B�w�������܂��B
struct _dictobject { PyObject_HEAD int ma_fill; /* # Active + # Dummy */ int ma_used; /* # Active */ �E �E } PyDictObject ==> PyObject �������������������������������� �������������������������������� ��int ob_refcnt; �� ��int ob_refcnt; �� ��struct _typeobject *ob_type;�� ==> ��struct _typeobject *ob_type;�� �� �� �������������������������������� ��int ma_fill; �� ��int ma_used; �� �� �E �� �� �E �� �� �� ��������������������������������
PyObject �� ob_refcnt �� reference count �����ŃI�u�W�F�N�g�̐����E���ł��Ǘ����邽�߂Ɏg���܂��B
ceval.c �̒��� machine code �����s�����邽�т� Py_INCREF(.), Py_INCREF(.), Py_XINCREF(.), Py_XDECREF(.) ���g��܂��B���̂��Ƃ́Apython virtual macnine code �����s���邽�тɃI�u�W�F�N�g����������A�܂���������邱�Ƃ��Ӗ����܂��B�����̃}�N���� object.h �Ŏ��̂悤�ɒ�`����Ă��܂�
#define Py_XINCREF(op) if ((op) == NULL) ; else Py_INCREF(op) #define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op) #define Py_INCREF(op) ( \ # in object.h _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ # ��f�o�b�O���͋� (op)->ob_refcnt++) #define Py_DECREF(op) \ if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \ # ��f�o�b�O���͋� --(op)->ob_refcnt != 0) \ _Py_CHECK_REFCNT(op) \ # ��f�o�b�O���͋� else \ _Py_Dealloc((PyObject *)(op))
�ȏ��� Python �ł̃K�[�x�[�W�E�R���N�V�����̓��t�@�����X�E�J�E���g�����ōs���Ă��邱�Ƃ�����܂��B�I�u�W�F�N�g�̃��t�@�����X�E�J�E���g�� 0 �ɂȂ邽�тɃI�u�W�F�N�g����������ă��������J������邱�Ƃ�����܂��B�g��Ȃ��Ȃ����I�u�W�F�N�g�S����Z�߂Ĉ�ӏ��ŏ����Ă���킯�ł͂Ȃ��Ɖ���܂��BPython ��g�ݍ��ݐ���p�r�Ɏg�����Ƃ��Ă��AJava �̂Ƃ��̂悤�ɃK�[�x�[�W�E�R���N�V�����ʼn����ł��Ȃ����Ԃ��W�����Ă��܂��킯�ł͂Ȃ����Ƃ�����܂��B
���ۂ� python �� id(.) �g�ݍ��݊����I�u�W�F�N�g�̃������E�A�h���X��Ԃ����Ɨ��p���āA���̂悤�Ƀ��X�g�E�I�u�W�F�N�g[0,1] ����������ɔz�u�����l�q��`���܂��BlstAt �ϐ��ŎQ�Ƃ��ꂽ���Ƃ́A���X�g�E�I�u�W�F�N�g[0,1]�͕ʂ̃������ʒu�ɐ�������܂��B
//@@ def testF(): print hex(id( [0,1] )) print hex(id( [0,1] )) lstAt = [0,1] print hex(id( [0,1] )) print hex(id( lstAt )) testF() import dis; dis.dis(testF) //@@@ 0x925698 0x925698 0x9252d8 0x925698 2 0 LOAD_GLOBAL 0 (hex) 3 LOAD_GLOBAL 1 (id) 6 LOAD_CONST 1 (0) 9 LOAD_CONST 2 (1) 12 BUILD_LIST 2 15 CALL_FUNCTION 1 18 CALL_FUNCTION 1 21 PRINT_ITEM 22 PRINT_NEWLINE 3 23 LOAD_GLOBAL 0 (hex) 26 LOAD_GLOBAL 1 (id) 29 LOAD_CONST 1 (0) 32 LOAD_CONST 2 (1) 35 BUILD_LIST 2 38 CALL_FUNCTION 1 41 CALL_FUNCTION 1 44 PRINT_ITEM 45 PRINT_NEWLINE 5 46 LOAD_CONST 1 (0) 49 LOAD_CONST 2 (1) 52 BUILD_LIST 2 55 STORE_FAST 0 (lstAt) 6 58 LOAD_GLOBAL 0 (hex) 61 LOAD_GLOBAL 1 (id) 64 LOAD_CONST 1 (0) 67 LOAD_CONST 2 (1) 70 BUILD_LIST 2 73 CALL_FUNCTION 1 76 CALL_FUNCTION 1 79 PRINT_ITEM 80 PRINT_NEWLINE 7 81 LOAD_GLOBAL 0 (hex) 84 LOAD_GLOBAL 1 (id) 87 LOAD_FAST 0 (lstAt) 90 CALL_FUNCTION 1 93 CALL_FUNCTION 1 96 PRINT_ITEM 97 PRINT_NEWLINE 98 LOAD_CONST 0 (None) 101 RETURN_VALUE
print hex(id( [0,1] )) �̂��т� BUILD_LIST ���߂� [0,1] �̃��X�g�E�I�u�W�F�N�g���q�[�v�E���������ɐ�������Ɠ����� PRINT_ITEM �������I���ƁA�������ꂽ [0,1] ���X�g�E�I�u�W�F�N�g�����Ă��܂��B���ڂ� print hex(id( [0,1] )) �ł� BUILD_LIST ���߂� [0,1] �̃��X�g�E�I�u�W�F�N�g���q�[�v�E���������ɐ�������̂ł����A�O��̏����ꂽ�������̏ꏊ�ɐ��������̂ŁA���ڂ� id( [0,1] ) ���O��̒l�Ɠ��� 0x925698 �ɂȂ�킯�ł��B�O��ڂ� [0,1] �̃��X�g�E�I�u�W�F�N�g���q�[�v�E���������ɐ�������Ƃ��ɂ́A�O��̃I�u�W�F�N�g���c���Ă��܂��B lstAt �ϐ��ŎQ�Ƃ���Ă��邽�߂ł��B�ł����� 0x925698 �Ƃ͕ʂ̃������̈ʒu�� [0,1] �̃��X�g�E�I�u�W�F�N�g �����˂Ȃ�܂���B���ۂɁA�O��ڂ� id( [0,1] ) �͐V�����������E�A�h���X 0x9252d8 �ɂȂ��Ă��܂��B
�����ł͊������ɂ����� python virtual machine code �̗l�q�����Ă����܂��B
�܂����Ăяo���� python interpreter ���ǂ�Ȃ��Ƃ����Ă��邩 python virtual machine code ���g���Č��Ă݂܂��傤�B���� python code �Ŋ��̐錾�ƁA���̌Ăяo�����Ɏ��s����� python virtual machine code ���o�͂ł��܂��B
//@@ def testF(inAg): print inAg testF(3) import kcommon as kc;kc.dis() //@@@ python temp.py 3 1 0 LOAD_CONST 0 (<code object testF at 0091FC20, file "temp.py", line 1>) 3 MAKE_FUNCTION 0 6 STORE_NAME 0 (testF) 4 9 LOAD_NAME 0 (testF) 12 LOAD_CONST 1 (3) 15 CALL_FUNCTION 1 18 POP_TOP �Esnip �E
��s�ڂ� def testF(.) �� testF �̃R�[�h�E�I�u�W�F�N�g���������� MAKE FUNCTION �������s�킹�Ă��܂��B Interpreter �ł��� Python �ł͊��̐錾�ɂ����s�������܂��B
4 �s�ڂ� testF(.) �ł́AtestF �t�@���N�V�����E�I�u�W�F�N�g(�ւ̎Q��)�ƈ��� 3 ���X�^�b�N�ɏ悹 CALL_FUNCTION �����s���Ă��܂��B�L�[���[�h�������Ȃ��P���ȏꍇ�� python ���Ăяo���� C �ł̊��Ăяo���Ǝ��Ă��܂��B
MAKE_FUNCTION �̏����ɂ��āA���˂�����Ō��Ă݂܂��傤�BMAKE FUNCTION �͊��I�u�W�F�N�g�����A��������̃��x���ɑΉ������܂��B���̂Ƃ������ɃO���[�o���ϐ��ƃf�t�H���g�����l�̐ݒ���s�킹�܂��B���̃e�X�g�E�R�[�h�������悤�ɁA���̐錾�����ŁA���Ȃ킿���̎��s��Ȃ��i�K�ŁA���Ȃ킿 CALL_FUNCTION �����s����O�ɁA���̂悤�Ɋ� testF(.) �� �f�t�H���g�����̒l�̃^�v����O���[�o���ϐ��̎����ɒl������U���Ă��܂��B���̃O���[�o���ϐ��� main module �̃O���[�o���ϐ��Ƃ��S�������ł��邱�Ƃ�����܂��Bmain ���W���[���ŁuinGlb=5�v�̂悤�ɃO���[�o���ϐ��������s���V�����o�Ă��āA��������s����ƁAtestF.func_globals �̒��g�������ɕς���čs���܂��B
//@@ #07.06.27 def testF(inAg = 3): return inGlb + inAg + 1 import pprint as pp;pp.pprint(testF.func_defaults ) print "---------------------" import pprint as pp;pp.pprint(testF.func_globals ) print "---------------------" inGlb = 5 import pprint as pp;pp.pprint(testF.func_globals ) print "---------------------" # global variables in main module import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_globals ) //@@@ (3,) --------------------- {'__builtins__':, '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'pp': , 'testF': } --------------------- {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'inGlb': 5, 'pp': , 'testF': } --------------------- {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'inGlb': 5, 'ins': , 'pp': , 'testF': }
ceval.c: C �\�[�X�E�R�[�h�́AMAKE_FUNCTION�̏������e���L�q����Ă��镔�������Ɏ����܂��BPyFunction_New(v, f->f_globals) �Ŋ��I�u�W�F�N�g�����Ă��܂��B���� v �� code_object �ւ̎Q�ƒl�ł��Bdata stack �ɐς܂�Ă��܂��BPyEval_EvalFrame(PyFrameObject *f) �̈��� f ���Ăяo�������g���Ă��� FrameObject �ւ̃|�C���^�ł��Bf->f_globals �l�� PyFunction_New(.) �����ɓn�����ƂŁA�V��������������I�u�W�F�N�g�̃O���[�o���ϐ��ւ̃|�C���^���A����錾�Fdef ���Ă��郂�W���[���̃O���[�o���ϐ��ւ̃|�C���l�ɐݒ肵�܂��B�ł������� testF(.) �̃R�[�h��Ŋ��̃O���[�o���ϐ��FtestF.func_globals �ƃ��W���[���̃O���[�o���ϐ��Fins.stack()[0][0].f_globals ���S�������l�ɂȂ�����ł��B���҂��������̂��|�C���g���Ă���̂ł�����B
PyObject * PyEval_EvalFrame(PyFrameObject *f) { �E �E case MAKE_FUNCTION: v = POP(); /* code object */ x = PyFunction_New(v, f->f_globals); Py_DECREF(v); /* XXX Maybe this should be a separate opcode? */ # oparg �ɂ̓f�t�H���g�l�t�������̌��������Ă��� if (x != NULL && oparg > 0) { v = PyTuple_New(oparg); if (v == NULL) { Py_DECREF(x); x = NULL; break; } while (--oparg >= 0) { w = POP(); #define PyTuple_SET_ITEM(op, i, v) # (((PyTupleObject *)(op))->ob_item[i] = v) PyTuple_SET_ITEM(v, oparg, w); } # FunctionObject.func_defaults ��ݒ肵�܂� err = PyFunction_SetDefaults(x, v); Py_DECREF(v); } PUSH(x); break; �E �E �E }
MAKE_FUNCTION �͊��̐錾�̏��Ŏ��s����� python virtual machine code �ł��B�f�o�b�K�ŃV���O���E�X�e�b�v���삳����Ƃ��A���̐錾�̏ꏊ�ň��~���܂��B���̂Ƃ� MAKE_FUNCTION �����s����Ă��܂��B���Ȃ킿 C �\�[�X�� ���̕��������s����Ă��܂��B
ceval.c �� MAKE_FUNCTION �̕����̃\�[�X��ǂ����ƂŁA���ꂪ���s�����Ƃ��̏������e�̏ڍׂ�����܂��B���̂��Ƃ�����܂��B
PyFunction_New(.) ���� ���ڍׂȓ����m�邽�߂ɂ́APyFunction_New(.) ���̃\�[�X�E�R�[�h��ǐՂ���K�v������܂��BGoogl Code Search ���g���ΊȒP�Ƀ\�[�X�ɒH�蒅���܂��B�Ⴆ�� PyFunction_New ���̏������e��������������� �����Ă��������B
���� C �\�[�X�E�R�[�h�̒��� PyFunction_New(.) �̏������e��H���Ă݂�� MAKE_FUNCTION ��
�ł��A������ C �\�[�X�E�R�[�h��ǐՂ��邱�Ƃ́A�ڍׂɂȂ肷���Ė{�e�ɂ͑�����������܂���B�������ŃR�[�h�̒ǐՂ��s���܂��B(�܂� C �\�[�X�ɏ����̉�������Ă��邾���ł��B)
���̃f�t�H���g�����l�͊��I�u�W�F�N�g�ɔz��Ƃ��Đݒ肳��܂��B�udef testF(inAg = 3):�v�̂悤�ȃf�t�H���g�����l���^����ꂽ���ł́AMAKE_FUNCTION �����s����O�ɁA�f�t�H���g�����l(�ւ̎Q��)�� data stack �ɐς܂�܂��B���̐ς܂ꂽ�l�����I�u�W�F�N�g�� func_defaults �z���o�[�ɐݒ肵�܂��B
����錾����Ƃ��ł͂Ȃ��A�Ăяo���Ƃ��uCALL_FUNCTION 1�v�̂悤�� CALL_FUNCTION �̃I�y�����h�ɂ͈����̌����ݒ肳��Ă��܂��B(���̌��̓R���p�C�����ɒ�܂�܂��B) ����Ŋ��� MAKE_FUNCTION �� FunctionObject.func_defaults[] �z��Ƀf�t�H���g�����l��ݒ肵�Ă���Ă��܂��B���̓���g���A�f�t�H���g�������܂߂������l����܂�܂��B
//@@ def testF(inAg = 3): inAt = 4 print inAt + inAg + 5 testF() testF(4) import kcommon as kc;kc.dis() import pprint as pp;pp.pprint(testF.func_defaults ) print "-------------------" print testF.func_code.co_varnames //@@@ python temp.py 8 9 1 0 LOAD_CONST 0 (3) # ���F�f�t�H���g�����l 3 LOAD_CONST 1 (<code object testF at 0091FC20, file "temp.py", line 1>) 6 MAKE_FUNCTION 1 # �I�y�����h�� 1 �̓f�t�H���g�����̌��ł� 9 STORE_NAME 0 (testF) 4 12 LOAD_NAME 0 (testF) 15 CALL_FUNCTION 0 18 POP_TOP 5 19 LOAD_NAME 0 (testF) 22 LOAD_CONST 2 (4) 25 CALL_FUNCTION 1 28 POP_TOP �Esnip �E (3,) ------------------- ('inAg', 'inAt')
MAKE_FUNCTION �ɂ��Ă� ceval.c �̉��̕����ŁA�f�t�H���g�����l��ێ�����^�v���̐����� FunctionObject.func_defaults �ւ̐ݒ���s���Ă��܂��B
PyObject * PyEval_EvalFrame(PyFrameObject *f) { �E �E case MAKE_FUNCTION: �E �E # oparg �ɂ̓f�t�H���g�l�t�������̌��������Ă��� if (x != NULL && oparg > 0) { v = PyTuple_New(oparg); if (v == NULL) { Py_DECREF(x); x = NULL; break; } while (--oparg >= 0) { w = POP(); #define PyTuple_SET_ITEM(op, i, v) # (((PyTupleObject *)(op))->ob_item[i] = v) PyTuple_SET_ITEM(v, oparg, w); } err = PyFunction_SetDefaults(x, v); Py_DECREF(v); } �E �E
���x�͊��̐錾�ł͂Ȃ��Ăяo��������Ƃ��� python interpreter ���s���Ă��邱�Ƃ̏ڍׂ����Ă����܂��傤�B
�����Ăяo���Ƃ��� CALL_FUNCTION �����s����܂��BCALL_FUNCTION �̏����ɂ��Ă��AMAKE FUNCTION �Ɠ��l�ɁA ceval.c �\�[�X�E�R�[�h��ǐՂ��邱�ƂŁA���ڍׂ܂œ˂�����Ō��邱�Ƃ��ł��܂��B
PyObject * PyEval_EvalFrame(PyFrameObject *f) { �E �E case CALL_FUNCTION: { PyObject **sp; #define PCALL(POS) pcall[POS]++ #As a result, the relationship among the statistics appears to be #PCALL_ALL == PCALL_FUNCTION + PCALL_METHOD - PCALL_BOUND_METHOD + # PCALL_CFUNCTION + PCALL_TYPE + PCALL_GENERATOR + PCALL_OTHER # ���� PCALL(.) �̓f�o�b�O���v���t�@�C�������W�߂邽�߂̃}�N���Ɛ������܂� PCALL(PCALL_ALL); # stack_pointer = f->f_stacktop; sp = stack_pointer; #ifdef WITH_TSC x = call_function(&sp, oparg, &intr0, &intr1); #else x = call_function(&sp, oparg); #endif stack_pointer = sp; PUSH(x); if (x != NULL) continue; break; } �E �E �E
call_function(.) �̌Ăяo����̏����� FrameObject ��V���ɐ������܂��BFrameObject.f_localsplus �� co_nlocals + co_stacksize �̃T�C�Y�̃��[�J���ϐ��Ɨ����𑫂����킹���X�^�b�N�̈���q�[�v�̈���ꊇ���Ċm�ہE�ݒ肵�܂��B���̐V���� FrameObject �� call_function(.) �̖߂�l�ł�����I�u�W�F�N�g�̒��Ɋ܂܂�Ă��܂��B�V���� FrameObject �� f_locals, f_globals �|�C���^�l��ݒ肵�܂��B
Python �ł͈��������[�J���ϐ��ł��Bco_varnames[] �z��ɂ͈������܂��[�J���ϐ��̕��������Ă��܂��Bco_varnames[] �̎n�߂̑��ɁA�����̏����ɏ]���������ϐ����������Ă��܂��Bfunc_code.co_varnames[] �Ɉ����ϐ���������Ă���̂ŁApython �̃L�[���[�h�����Ăяo�����\�ɂȂ�܂��B
call_function(.) ���̓�������Ăяo�� fast_function(.) �� co_nlocals + co_stacksize �̃T�C�Y�̃��[�J���ϐ��ƃX�^�b�N�̗����𑫂����킹���̈���q�[�v�̈���m�ۂ��܂��B���Ăяo������ data stack �ɐς�ł�������l�ƁA MAKE_FUNCTION ���ݒ肵�Ă��ꂽ FunctionObject.func_defaults �̓����A�V�K�Ɋm�ۂ��� FrameObject.f_localsplus �ɁA�����̃��[�J���ϐ��l��ݒ肵�܂��B
���̉ߒ��̏ڍׂ𗝉�����ɂ́A���� C ���� sourse ��ǂ��Ă����˂Ȃ�܂���B�ł�����͏ڍׂɂȂ肷����̂������瑤�� C sourse �Ɛ����������Ă����܂��B
case CALL_FUNCTION �� static PyObject * call_function(PyObject ***pp_stack, int oparg) ��DLL �����ۂ��ŏ�����U�蕪���܂� static PyObject * fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) # ���� FrameObject �����܂� # �f�t�H���g�����A�L�[���[�h�������Ȃ���� PyEval_EvalFrame(.) ���Ăяo���܂� ��# �f�t�H���g�����E�L�[���[�h����������Ƃ����̏������lj��ōs���܂� PyObject * PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, PyObject **args, int argcount, PyObject **kws, int kwcount, PyObject **defs, int defcount, PyObject *closure) # �L�[���[�h�����E�L�[���[�h����������Ƃ��̏��� ��# python machine code �̎��s PyObject * PyEval_EvalFrame(PyFrameObject *f)
python �ɂ�����ϐ��̃X�R�[�v�̋K���� LEGB ���[���Ő�������܂��B���̐����̔w��ɂ���l�������Adisassembler �̏o�͂Ɗ��� func_code ��������f�����Ƃ��ł��܂��B
O'REYLLY ����o�ł���Ă���u���߂Ă� python�v�́u13 �́F�ϐ��ƃX�R�[�v�v�ɁA�ϐ��̎Q�Ƃ� LEGB ���[���ʼn��������A����local, enclosure, global, builtin �̏����ŎQ�Ɛ��T���Ă����Ə�����ĂĂ��܂��B�����ł� closure �͏����ʓ|�Ȃ̂Ō�ň������ƂƂ��Alocal, global builtin �̎O��ނ����̗�Ɍ��肵�� python virtual machine �̎��_���猩�Ă݂܂��傤�B
�����ň�����ϐ��̎Q�Ƃ̏ڍׂȉ������@�́A disassembler �o�͂Ɗ��� func_code �������痝���ł��܂��B
//@@ inGlb = 3 def testF(inAg): global inGlb inAt = inAg + inGlb + 3 inGlb = 4 return inAg + inGlb import dis;dis.dis(testF) print "------------------" print "co_varnames:", testF.func_code.co_varnames print "co_names: ", testF.func_code.co_names print "co_consts: ", testF.func_code.co_consts #testF(3) //@@@ 4 0 LOAD_FAST 0 (inAg) 3 LOAD_GLOBAL 1 (inGlb) 6 BINARY_ADD 7 LOAD_CONST 1 (3) 10 BINARY_ADD 11 STORE_FAST 1 (inAt) 5 14 LOAD_CONST 2 (4) 17 STORE_GLOBAL 1 (inGlb) 6 20 LOAD_FAST 0 (inAg) 23 LOAD_GLOBAL 1 (inGlb) 26 BINARY_ADD 27 RETURN_VALUE ------------------ co_varnames: ('inAg', 'inAt') co_names: ('inAg', 'inGlb', 'inAt') co_consts: (None, 3, 4)
��� disassembler ���ʂ��킩��悤�Ƀ��[�J���ϐ��ɂ� LOAD_FAST/STORE_FAST ���A�O���[�o���ϐ��ɂ� LOAD_GLOBAL/STORE_GLOBAL ���g���܂�
LOAD_FAST/STORE_FAST �� LOAD_GLOBAL/STORE_GLOBAL �̓��ނ̖��߂��g�������āA�ϐ��ւ̃A�N�Z�X���@��ς��Ă��܂��BLOAD_FAST/STORE_FAST �͊��Ăяo�����Ƃɐ݂����郍�[�J���ϐ��̔z��ɃC���f�b�N�X���g���č����ɃA�N�Z�X���܂��B����� LOAD_GLOBAL/STORE_GLOBAL �ϐ���������g���ăO���[�o���ϐ��������A�N�Z�X���܂��B���[�J���ϐ��ւ̃A�N�Z�X�̂ق����A������̔�r���O���[�o���ϐ��ւ̃A�N�Z�X���{���x�����Ȃ�܂��B
���� global �錾���Ă��Ȃ��ϐ��ł� co_names �^�v���������ɔz�u���� co_varnames ���ɔz�u����Ă��Ȃ��ϐ��́ALOAD_GLOBAL/STORE_GLOBAL �����蓖�Ă��܂��B�����Ŏg���Ă���A global �錾����Ă��Ȃ��ϐ��� local/global �ǂ���ɂȂ邩�́A���l�ɂȂ邩�ۂ��Ō��܂�܂��B
//@@ inGlb = 3 def testF(inAg): #global inGlb inAt = inAg + inGlb + 3 #inGlb = 4 return inAg + inGlb import dis;dis.dis(testF) print "------------------" print "co_varnames:", testF.func_code.co_varnames print "co_names: ", testF.func_code.co_names print "co_consts: ", testF.func_code.co_consts #testF(3) //@@@ 4 0 LOAD_FAST 0 (inAg) 3 LOAD_GLOBAL 1 (inGlb) 6 BINARY_ADD 7 LOAD_CONST 1 (3) 10 BINARY_ADD 11 STORE_FAST 1 (inAt) 6 14 LOAD_FAST 0 (inAg) 17 LOAD_GLOBAL 1 (inGlb) 20 BINARY_ADD 21 RETURN_VALUE ------------------ co_varnames: ('inAg', 'inAt') co_names: ('inAg', 'inGlb', 'inAt') co_consts: (None, 3)
��� python virtual machine code ������Ή���悤�ɁA���[�J���ϐ��ɂ� LOAD_FAST/STORE_FAST ���g���܂��B�O���[�o���ϐ��ɂ� LOAD_GLOBAL/STORE_GLOBAL ���g���܂��B��̃R�[�h��ł� inGlb �� global ����Ă��܂���B�ł����l�ɂ��Ȃ��Ă��Ȃ��̂� global �ϐ��Ƃ݂Ȃ���Ă��܂��B
�Ȃ������ł̃��W���[�����i���̃R�[�h��ł� bisec ���W���[�����j�̓��[�J���ϐ��ł��Bbisect �� STORE/LOAD �� STORE_FAST/LOAD_FAST ���߂��g���܂��B
//@@ def testF(): import bisect print bisect print var import dis;dis.dis(testF) //@@@ 2 0 LOAD_CONST 0 (None) 3 IMPORT_NAME 0 (bisect) 6 STORE_FAST 0 (bisect) 3 9 LOAD_FAST 0 (bisect) 12 PRINT_ITEM 13 PRINT_NEWLINE 14 LOAD_CONST 0 (None) 17 RETURN_VALUE
�r���g�C���ϐ��� interpreter ����݂�O���[�o���ϐ��ł��B�r���g�C���ϐ��ɂǂ�Ȃ��̂����邩�͉��̃R�[�h�ɂ�蒲�ׂ��܂��B
//@@ import pprint as pp pp.pprint( vars(__builtins__) ) //@@@ {'ArithmeticError':, �Esnip �E '__import__': , '__name__': '__builtin__', 'abs': , 'apply': , �E �E 'tuple': , 'type': , 'unichr': , 'unicode': , 'vars': , 'xrange': , 'zip': }
�r���g�C���ϐ����O���[�o���ϐ��ł��邱�Ƃ́A���̃R�[�h�́uprint zip�v���� LOAD_GLOBA �ɂȂ邱�Ƃ������܂��BPython interpreter �� FrameObject.f_globals �����ɃO���[�o���ϐ�����������Ȃ�������A�r���g�C���ϐ�������T���悤�ɂ��Ă��邾���ł��B
//@@ def testF(): print zip # zip built-in function object testF() import dis; dis.dis(testF) //@@@ python temp.py2 0 LOAD_GLOBAL 0 (zip) # ������ "zip" �ւ̎Q�� 3 PRINT_ITEM 4 PRINT_NEWLINE 5 LOAD_CONST 0 (None) 8 RETURN_VALUE
�O���[�o���ϐ��Ƃ����Ă��A���̃X�R�[�v�̓��W���[�����Ɍ����܂��BC ����̂Ƃ��̂悤�ɁA�v���O�����S�̂ɋy�ԃX�R�[�v�����ϐ��͂���܂���B
���ł� MAKE_FUNCTION �����s�����Ƃ��ɁA�Q�Ƃ��Ă���O���[�o���ϐ��I�u�W�F�N�g�Ɗ����̃O���[�o���ϐ����x���Ƃ̊Ԃ̑Ή�����܂�܂��B����Ŋ��I�u�W�F�N�g�͎����^�яo���܂��B�ʂ̕ϐ��X�R�[�v�̊��Ŏ��s����܂��B�ł����I�u�W�F�N�g�̎����^�тł́A�O���[�o���ϐ���ێ����� FunctionObject.f_globals ���ꏏ�Ɉړ����܂��B�����łȂ���A���삪�ۏ���܂���B
python �ł͑S�Ă̕ϐ��̓f�t�H���g�� public �ł��B���W���[���� global �ϐ��� builtin �ϐ��ł������A���[�U�[�̕K�v�ɉ����ď���ɕύX�\�ł��B�ł��Apublic ������Ƃ����ĕʃ��W���[���ɉe����^����悤�ȕύX�͂ł��܂���Bbuiltin �����ϐ��̓��W���[�����X�R�[�v���Ƃɐ݂����Ă��邩��ł��B�ǂ����̃��W���[���� builtin �ϐ�������ɕύX���Ă��Ă��A���̃��W���[���̃��[�U�[�ɂ͉e�����܂���B���Ӑ[�� ����肭�l�����Ă��܂��B
//@@ #print testF #inGlb = 3 def testF(inAg=3): inAt = 5 print inAg + inAt + inGlb import inspect as ins; import pprint as pp; pp.pprint(ins.getmembers(testF) ) //@@@ [('__call__',���̂悤�� FunctionObject.func_globals ���������o���܂�), ('__class__', ), ('__delattr__', ), ('__dict__', {}), ('__doc__', None), ('__get__', ), ('__getattribute__', ), ('__hash__', ), ('__init__', ), ('__module__', '__main__'), ('__name__', 'testF'), ('__new__', ), ('__reduce__', ), ('__reduce_ex__', ), ('__repr__', ), ('__setattr__', ), ('__str__', ), ('func_closure', None), ('func_code', <code object testF at 0091FC20, file "temp.py", line 3>), ('func_defaults', (3,)), ('func_dict', {}), ('func_doc', None), ('func_globals', {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'ins': , 'pp': , 'testF': }), ('func_name', 'testF')]
//@@ #print testF def testF(inAg=3): inAt = 5 print inAg + inAt # print testF.func_locals # testF dose not have a func_locals attribute. print testF.func_globals //@@@ python temp.py {'__builtins__':, '__name__': '__main__', '__file__': 'temp.py', '__doc__': None, 'testF': }
���̂悤�Ɋ��� function.func_globals �� FrameObject.f_globals �͓������̂ł��BC source ��ł́A�ǂ�������� global �ϐ��̎����I�u�W�F�N�g���w���Ă��܂��B
//@@ def testF(inAg=3): inAt = 5 print inAg + inAt #import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_globals ) import inspect as ins; print(ins.stack()[0][0].f_globals ) print testF.func_globals testF() //@@@ python temp.py {'__builtins__':, '__name__': '__main__', '__file__': 'temp.py', '__doc__': None, 'testF': } 8 {'__builtins__': , '__name__': '__main__', '__file__': 'temp.py', '__doc__': None, 'testF': }
�������Ƀf�t�H���g����������� func_defaults �v�f����������܂��BMAKE_FUNCTION �� FunctionObject.func_defaults ���E�ݒ肵�܂��B
//@@ #07.06.27 def testF(inAg = 3): return inAg + 1 print "Default Argment Value:", testF.func_defaults //@@@ Default Argment Value: (3,)
���̃f�t�H���g�����̒l�� MAKE_FUNCTION ���s�����Ƃ��� FunctionObject �̒��ɒ~�����܂��B��ŕύX����邱�Ƃ͂���܂���B
//@@ inGlb = 3 def testF(inAg = inGlb): return inAg + 1 print testF(10) inGlb = 5 print testF(10) //@@@ 11 11
���̂悤�ɁA���Ƃ����ł��N���X�̎��̂悤�Ƀ����o�[��lj��ł��܂��B���̂Ƃ� func_dict �ɂ́A���̒lj������o�[�������Ă��܂��B���̂悤�ȃf�[�^�E�����o�[�����ɒlj����邱�Ƃ��{���ɕK�v���͋^��ł��B����Ȏg���������ɑ��Ďg���l�͖w�ǂ��Ȃ��Ǝv���܂��B���� ���̗�� python �̃I�u�W�F�N�g�͊�{�I�Ȓi�K�Ŏ����I�u�W�F�N�g��t���ł����悤�ɍ���Ă��邱�Ƃ��Ӗ����Ă��܂��B
//@@ #07.06.27 def testF(inAg = 3): return inAg + 1 testF.m_in = 4 print "testF.func_dict:", testF.func_dict //@@@ testF.func_dict: {'m_in': 4}
���܂Ő������Ă������[�J���^�O���[�o���ϐ��ɂ��Ă̒m����O��ɁA�����ł̓��[�J���ϐ��� data stack �ɏo�����ꂷ�� STORE_FAST/LOAD_FAST ���߂ɂ��ďڂ����݂Ă݂܂��傤�B
���̃R�[�h��Ŏ�����Ă���悤�ɁA���[�J���ϐ� inAt1, inAt2 �ւ̓ǂݏ����́uSTORE_FAST i/LOAD_FAST i�v���߂ōs���܂��B
//@@ def testF(): inAt1 = 3 inAt2 = 5 print inAt1 + inAt2 f_locals import dis;dis.dis(testF) print testF.func_code.co_varnames //@@@ 2 0 LOAD_CONST 1 (3) 3 STORE_FAST 1 (inAt1) 3 6 LOAD_CONST 2 (5) 9 STORE_FAST 0 (inAt2) 4 12 LOAD_FAST 1 (inAt1) 15 LOAD_FAST 0 (inAt2) 18 BINARY_ADD 19 PRINT_ITEM 20 PRINT_NEWLINE 5 21 LOAD_GLOBAL 2 (f_locals) 24 POP_TOP 25 LOAD_CONST 0 (None) 28 RETURN_VALUE ('inAt2', 'inAt1')
�uSTORE_FAST i/LOAD_FAST i�v���߂̃C���f�b�N�X i �� testF.func_code.co_varnames:('inAt2', 'inAt1') �z��̃C���f�b�N�X�ɑΉ����܂��B������ testF.func_code.co_varnames ���͕̂�����̔z��ɂ����܂���B���ۂɃf�[�^���ǂݏ��������̂́AFrameObject �̒��ɍ���郍�[�J���ϐ��̈�ł��Bco_varnames ������z��̓R���p�C������ �uSTORE_FAST i/LOAD_FAST i�v�̃C���f�b�N�X�l�����߂�̂ɗ��p����邾���ł��B
���[�J���ϐ��̈�̓q�[�v�̈�Ɋm�ۂ���AFrameObject �̒��� data stack �̈�ƈꏏ�ɕێ�����܂��B���̊J�n�A�h���X�� C �\�[�X���ł� FrameObject.f_localsplus �����o�[�ɋL�^����Ă��܂��B
���[�J���ϐ��̈�̓q�[�v�̈悪 data stack �̈�ƈꏏ�Ɉ��Ƃ��Ċm�ۂ����̂ɂ͋������R�͂���܂���B���[�J���ϐ��̐��ƃX�^�b�N�E�T�C�Y�̓R���p�C�����ɒ�܂�A���ꂪ�R�[�h�I�u�W�F�N�g�ɋL�^����Ă��邽�߁ACodeObject.co_nlocals + Code.Object.co_stacksize ���v�Z���āA�܂Ƃ߂ė����̃q�[�v�̈���m�ۂ����ق����������Ԃ������ł��Z���ł�����x�̈Ӗ���������܂���B
�uSTORE_FAST i/LOAD_FAST i�v���߂̎��ۂ̏������e������ ceval.c �̃\�[�X�E�R�[�h���������Ɏ����܂��B
#define PyTuple_SET_ITEM(op, i, v) (((PyTupleObject *)(op))->ob_item[i] = v) #define SETLOCAL(i, value) do { PyObject *tmp = GETLOCAL(i); \ GETLOCAL(i) = value; \ Py_XDECREF(tmp); } while (0) #define GETLOCAL(i) (fastlocals[i]) co = f->f_code; names = co->co_names; consts = co->co_consts; fastlocals = f->f_localsplus; �E �E if (HAS_ARG(opcode)) # LOAD_FAST i �Ȃǂ� opecode �������߂̂Ƃ� # i �l�� oparg �ϐ��ɓ���� oparg = NEXTARG(); �E �E case LOAD_FAST: #define GETLOCAL(i) (fastlocals[i]) x = GETLOCAL(oparg); if (x != NULL) { Py_INCREF(x); PUSH(x); goto fast_next_opcode; �A�����Ď��̏����Ɉڂ� } format_exc_check_arg(PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(co->co_varnames, oparg)); break; �E �E case STORE_FAST: v = POP(); SETLOCAL(oparg, v); goto fast_next_opcode;
oparg �ɁuSTORE_FAST i/LOAD_FAST i�v���߂̃I�y�E�R�[�h�A���Ȃ킿�C���f�b�N�X i �̒l������܂��B���̃C���f�b�N�X�l�ɏ]���� FrameObject.f_localsplus ����n�܂�I�[�g�ϐ��̎Q�Ƃ̔z��̈�ɏ������݁A�܂��ǂݍ��݂����Ă��܂��BLOAD_FAST ���߂ł̓��t�@�����X�E�J�E���g�̃C���N�������g���s�킹�Ă��܂��B
�܂��uSTORE_FAST i/LOAD_FAST i�v���߂̂��Ȃ킿�C���f�b�N�X�́A �ϐ������������Ă��� func_code.co_varnames[] �̃C���f�b�N�X�ɑΉ����邱�Ƃ��A�ēx�w�E���Ă����܂��B
���x�̓O���[�o���ϐ��̓ǂݏ����ɂ��ďڍׂɌ��Č��܂��傤�B �O���[�o���ϐ��̂Ƃ��́A���[�J���ϐ��̂Ƃ��̂悤�ɃR���p�C�����ɒ�܂�z��C���f�b�N�X���ɂ��l�����o���^�����ł��܂���BPython �̃O���[�o���ϐ��͉��̃R�[�h�Ⴉ�������悤�ɁA�v���O�����ɂ���ă_�C�i�~�b�N�ɒlj�����Ă������̂�����ł��B���W���[���ɍ����O���[�o���ϐ������� key ������ƁA�����̃O���[�o���ϐ���������O���[�o���ϐ��̒l�����o���܂��B
//@@ # 07.07.16 add global variable by subroutin def addToGlobalVariable(dctAg): dctAg['inGlb'] = "xyz" def testF(): print inGlb addToGlobalVariable(globals()) testF() import dis;dis.dis(testF) print testF.func_code.co_names //@@@ C:\my\vc7\mtCm>python temp.py xyz 6 0 LOAD_GLOBAL 0 (inGlb) 3 PRINT_ITEM 4 PRINT_NEWLINE 5 LOAD_CONST 0 (None) 8 RETURN_VALUE ('inGlb',)
��̃v���O������������܂��B�r���g�C���� globals() �́A���W���[���̃O���[�o���ϐ��̎�����Ԃ��܂��B���̎����� addToGlobalVariable(.) ���̈����ɓn���Ă��A ('inGlb', 'xyz') �� key �� value �̑g���O���[�o���ϐ������ɒlj����Ă��܂��B testF() ���̒��ŁA�lj����ꂽ inGlb �ϐ��̒l���R���\�[���ɑł��o���Ă��܂��B
Disassemble ���ʂ́uLOAD_GLOBAL 0�v���߂������̕ϐ�������z����C���f�b�N�X 0 �̕�����Q�ƒl�����o���� data stack �ɒl���悹�鏈�����s���܂��B�����Łu0� �� testF.func_code.co_names ���ϐ��������� 'inGlB' �����o�����߂̃C���f�b�N�X�l�ł��B���̃C���f�b�N�X�l�̓R���p�C�����ɒ�܂�܂��B������ f_code.co_names[0] �ɂ���ϐ���������� FrameObject.f_globals �|�C���^���A�O���[�o���ϐ����w�������I�u�W�F�N�g�� �T���o�� push(X):stack �ɏ悹�܂��BFrameObject.f_globals �ɒT���Ă��镶�������Ƃ��� FrameObject.f_builtins ��T���܂�
���X MAKE_FUNCTION ���߂������W���[���� FrameObject �̃O���[�o���ϐ��ւ̃|�C���^���A���I�u�W�F�N�g�� func_globals �v�f�ɐݒ肵�Ă��܂����B���̒l���ACALL_FUNCTION �� FrameObject ������Ƃ� FrameObject.f_globals �ɃR�s�[���܂��B���̂��� FrameObject �̃O���[�o���ϐ��͊����錾���ꂽ�Ƃ��̃��W���[���̃O���[�o���ϐ��ւ̃|�C���^�ɐݒ肳��Ă��܂��B���� FrameObject.f_globals ������� f_code.co_name[i] �ϐ���������L�[�Ƃ���l���uLOAD_GLOBAL i�v�ɂ���Ď��o�� data stack �ɏ悹�܂��B
LOAD_GLOBAL i # testF.func_code.co_names[i] �̕�����z���� "inGlb" ����������o�� �� func_code->co_names[i] --> --> "inGlb" string # �ϐ��������� �� function FramObject.f_globals �� module FrameObject.f_globals �� # ���W���[���̃O���[�o���ϐ� # ������ key() �ɑΉ����� # value �����o�� Module global variable
���� ceval.c �ɂ��� STORE_GLOBAL/LOAD_GLOBAL �̏������e�̕����������܂��B
case STORE_GLOBAL: w = GETITEM(names, oparg); v = POP(); err = PyDict_SetItem(f->f_globals, w, v); Py_DECREF(v); if (err == 0) continue; break; �E �E case LOAD_GLOBAL: # co_names[] ���C���f�b�N�X oparg �ɑΉ����镶����ւ̎Q�Ƃ� w �ɗ^���� w = GETITEM(names, oparg); if (PyString_CheckExact(w)) { # w ��������ł���A�����瑤�� inline �ɁA�����ɏ������� # �����ŃO���[�o���������� w ������L�[�����l�����o�� /* Inline the PyDict_GetItem() calls. WARNING: this is an extreme speed hack. Do not try this at home. */ long hash = ((PyStringObject *)w)->ob_shash; if (hash != -1) { PyDictObject *d; d = (PyDictObject *)(f->f_globals); x = d->ma_lookup(d, w, hash)->me_value; if (x != NULL) { Py_INCREF(x); PUSH(x); # LOAD_GLOBAL �������I������̂� # ���� machine code �̉�͂Ɉڂ� continue; } # f->f_globals �� w ��������Ȃ������̂� # f->f_builtins ���� w ��T�� d = (PyDictObject *)(f->f_builtins); x = d->ma_lookup(d, w, hash)->me_value; if (x != NULL) { Py_INCREF(x); PUSH(x); # LOAD_GLOBAL �������I������̂� # ���� machine code �̉�͂Ɉڂ� continue; } goto load_global_error; } } /* This is the un-inlined version of the code above */ x = PyDict_GetItem(f->f_globals, w); if (x == NULL) { x = PyDict_GetItem(f->f_builtins, w); if (x == NULL) { load_global_error: format_exc_check_arg( PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w); break; } } Py_INCREF(x); PUSH(x); continue;
LOAD_FAST �̊Ȍ��ȏ����Ɣ�r����ƁA���X�������������܂��B�O���[�o���ϐ��������L�[������������Ɍ������邽�� hash ���g���Ă���̂ŁA�R�[�h�͕��G�ɂȂ��Ă��܂��܂��B���̏ڍׂ� PyDict_SetItem(.) ���� PyDict_GetItem(.) ���ɂ���܂��B��� C �\�[�X�̃{�[���h�̕����̕������O���[�o���ϐ���������ϐ���������̃L�[�������Ēl�����o���Ă��镔���ł��B
���̂悤�� decrement ���s���Ԃ��v�����Ă݂�� global/local �̈Ⴂ�� global �̂ق�����{���x�����̏������Ԃ�������܂��B��������L�[�������T���o�������ƃ��[�J���ϐ��z��C���f�b�N�X�Œ��ڎ��o���������I�ɔ�r����C���[�W���炷��ƁA�{�ōςނ̂��ȊO�Ɋ����܂��B���̏��������������邽�� hash �l���I�u�W�F�N�g�Ɏ���������v�Z�����Ȃ��ȂǁA�l�X�̃e�N�j�b�N���g���Ă��܂��B���̗͂ł͊Ȍ��ɐ����ł��܂���B�����̂������ C �\�[�X��ǂ��Ă��������B
//@@ NGlb = 100000 inGlb = NGlb def testGlobalF(): global inGlb while(inGlb > 0): inGlb -= 1 inGlb = inGlb # repeat 10 times inGlb = inGlb # to avoid CPU cash effect inGlb = inGlb inGlb = inGlb inGlb = inGlb inGlb = inGlb inGlb = inGlb inGlb = inGlb inGlb = inGlb inGlb = inGlb def testLocalF(): inAt = NGlb while(inAt > 0): inAt -= 1 inAt = inAt # repeat 10 times inAt = inAt # to avoid CPU cash inAt = inAt inAt = inAt inAt = inAt inAt = inAt inAt = inAt inAt = inAt inAt = inAt inAt = inAt import time tmBeforeAt = time.clock() testLocalF() print time.clock()-tmBeforeAt tmBeforeAt = time.clock() testGlobalF() print time.clock()-tmBeforeAt //@@@ python temp.py 0.0623292609314 0.112814522461
Python virtual machine code �����Ă���ƁA���ł����W���[���ł��w�Ǔ������Ƃ����Ă��邱�Ƃ�����܂��B�ł����̃R�[�h��ł�������悤�Ɋ��ł� STORE_GLOBAL ���g���Ă����̂ɁA���W���[���ł� STORE_NAME ���g���Ƃ��������ȈႢ������܂��B�����ł� STORE_GLOBAL �� STORE_NAME �� �ǂ�ȈႢ������̂��ׂ܂��B
//@@ def testF(): global inGlb inGlb = 3 inGlb = 5 print "------- disassemble testF() --------" import dis; dis.dis(testF) print "------- disassemble module --------" import kcommon as kc; kc.dis() import inspect as ins; print(ins.stack()[0][0].f_globals ) import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_code.co_names ) //@@@ python temp.py 5 ------- disassemble testF() -------- 2 0 LOAD_CONST 1 (3) 3 STORE_FAST 0 (inAt) 3 6 LOAD_FAST 0 (inAt) 9 PRINT_ITEM 10 PRINT_NEWLINE 4 11 LOAD_GLOBAL 1 (inGlb) 14 PRINT_ITEM 15 PRINT_NEWLINE 16 LOAD_CONST 0 (None) 19 RETURN_VALUE ------- disassemble module -------- 1 0 LOAD_CONST 0 (<code object testF at 0091FC20, file "temp.py", line 1>) 3 MAKE_FUNCTION 0 6 STORE_NAME 0 (testF) 6 9 LOAD_CONST 1 (5) 12 STORE_NAME 1 (inGlb) 7 15 LOAD_NAME 1 (inGlb) 18 PRINT_ITEM 19 PRINT_NEWLINE �Esnip �E
STORE_GLOBAL �� STORE_NAME �ɂ��� python �̃��t�@�����X�E�}�j���A���ɂ͉��̂悤�ɏ����Ă���܂��B
STORE_GLOBAL namei Works as STORE_NAME, but stores the name as a global STORE_NAME�Ƃ��ċ@�\���܂����A�O���[�o���Ƃ��Ė��O���L�����܂��B STORE_NAME namei Implements name = TOS. namei is the index of name in the attribute co_names of the code object. The compiler tries to use STORE_LOCAL or STORE_GLOBAL if possible. name = TOS�����s���܂��Bnamei�̓R�[�h�I�u�W�F�N�g�̑���co_names�ɂ�����name�� �C���f�b�N�X�ł��B�R���p�C���͉\�Ȃ��STORE_LOCAL�܂���STORE_GLOBAL���g���� �Ƃ��܂��B
���̐����ł́u�悤�������v�Ƃ��������啔�����Ǝv���܂��B�Ȃ̂� ceval.c �ɓ��ݍ���Ō��Ă݂܂��B
case STORE_GLOBAL: w = GETITEM(names, oparg); v = POP(); err = PyDict_SetItem(f-<f_globals, w, v); Py_DECREF(v); if (err == 0) continue; break; case STORE_NAME: w = GETITEM(names, oparg); v = POP(); # value if ((x = f-<f_locals) != NULL) { #define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type) if (PyDict_CheckExact(x)) # f_locals �������FPyDict_Type �Ȃ̂� STORE_GLOBAL �� # �Ƃ��Ɠ��l�ɁA�ϐ�����������g���� hash �l�o�R�� �l # ��ݒ肷��B���̂Ƃ� f_locals �����ւ� key, value �� # �ݒ���s���Ă����B�f�t�H���g�����T�C�Y�ł͑���Ȃ��� # �����玫���̍�蒼�����s�� err = PyDict_SetItem(x, w, v); else # w �� ob_ival �������g���� local �ϐ��l���C���f�b�N�X�Őݒ肷�� err = PyObject_SetItem(x, w, v); Py_DECREF(v); if (err == 0) continue; break; } PyErr_Format(PyExc_SystemError, "no locals found when storing %s", PyObject_REPR(w)); break; �E �E case LOAD_NAME: w = GETITEM(names, oparg); if ((v = f->f_locals) == NULL) { PyErr_Format(PyExc_SystemError, "no locals when loading %s", PyObject_REPR(w)); break; } if (PyDict_CheckExact(v)) { # x = PyDict_GetItem(v, w); Py_XINCREF(x); } else { # FrameObject.f_locals �������� ob_ival �������g���ăC���f�b�N�X�Őݒ肷�� x = PyObject_GetItem(v, w);f_globals, w); if (x == NULL) { x = PyDict_GetItem(f->f_builtins, w); if (x == NULL) { format_exc_check_arg( PyExc_NameError, NAME_ERROR_MSG ,w); break; } } Py_INCREF(x); } PUSH(x); continue;
�v�̓��[�J���ϐ��̑��݂��Ȃ��g�b�v���x���̏����ł��A�������̂��߂Ɋ��̎��Ɠ��l�ɃC���f�b�N�X�g�������[�J���ϐ��z��ł̃A�N�Z�X���g���Ƃ������Ƃł��B���Ƃ��ƃ��W���[���̃g�b�v�E���x���ł̓��[�J���ϐ��͑��݂��܂���B�ł� FrameObject �͂���̂ł�����A���̂Ƃ��Ɠ��l�Ƀ��[�J���ϐ��̈������Ă���Ă���肠��܂���B�B���ۂɉ��̂悤�Ƀ��W���[���� f_locals/f_globals ��inspect ���Ă��� f_local �������ɂ͑��݂��܂��B�ł� f_globals �Ɠ����l�ɂȂ��Ă��܂��Bg_globasl �� f_locals �̗��������s�ɔ����đ����Ă����܂��B
//@@ if True: inAt = 3 # inAt is global variable print range # range is built in function object import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_locals ) print "-----------------" import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_globals ) print "----------------------------------" inGlb = 5 print range # range is built in function object import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_locals ) print "-----------------" import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_globals ) print "----------------------------------" import dis;import inspect as ins;dis.dis(ins.stack()[0][0].f_code) //@@@ python temp.py{'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'inAt': 3, 'ins': , 'pp': } ----------------- {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'inAt': 3, 'ins': , 'pp': } ---------------------------------- {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'inAt': 3, 'inGlb': 5, 'ins': , 'pp': } ----------------- {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'inAt': 3, 'inGlb': 5, 'ins': , 'pp': } ---------------------------------- 1 0 LOAD_NAME 0 (True) 3 JUMP_IF_FALSE 10 (to 16) 6 POP_TOP 2 7 LOAD_CONST 0 (3) 10 STORE_NAME 1 (inAt) 13 JUMP_FORWARD 1 (to 17) << 16 POP_TOP 4 << 17 LOAD_NAME 2 (range) 20 PRINT_ITEM 21 PRINT_NEWLINE �Esnip �E
���W���[���̃g�b�v�E���x���̕ϐ��� global �ϐ��ł��B�ł��������Ă��邱�Ƃ͊��̃I�[�g�ϐ��Ɩw�Ǔ����ł��B�Ⴂ������Ƃ���A���� FrameObject.f_globals �� CALL_FUNCTION �̏������ɐݒ肳��܂��B�ł����W���[���̃g�b�v�E���x���̏����ł� FramObject.f_globals ��ݒ肷��͎̂������g�ł��B�����炱�����W���[���ł� STORE_FAST/LOAD_FAST �̑����STORE_NAME/LOAD_NAME ���߂��g�����ƂŁA���Ɩw�Ǔ��������ōς܂��Ȃ���A���W���[���� FrameObject.f_globals ��ݒ肵�Ă�����Ƃ�������悤�ɂ��Ă���̂ł��傤�B
�Ȃ����ɏq�ׂ�N���X�ł� STORE_NAME/LOAD_NAME ���g���̂ł����A������ł� f_locals ��������lj����Ă����܂��B
�N���X�Ɗ��� virtual machine code �̖ʂ��猩��� �悭���Ă��܂��B���ۃN���X�ł����Ă��A���� python �R�[�h�����s�������Ƃ��A�N���X�������Ȃ��̊��ł��邩�̂悤�Ɏ��s����Ă��܂��܂��B�uprint m_inStt�v�����s����� 3 ���R���\�[���ɏo�͂���܂��B
//@@ class ClTest: m_inStt = 3 print m_inStt def __init__(self, inAg =3): self.m_in = inAg //@@@ python temp.py 3
�N���X�錾�̉ӏ��� python interpreter ���ǂ̂悤�Ȃ��Ƃ� �s���Ă��邩�́A���̂悤�� python virtual machin code ��f���o�����Ă�邱�ƂŔ`�����߂܂��B
//@@ class ClTest: m_inStt = 3 print m_inStt def __init__(self, inAg =3): self.m_in = inAg import kcommon as kc; kc.dis() //@@@ 3 1 0 LOAD_CONST 0 ('ClTest') 3 BUILD_TUPLE 0 6 LOAD_CONST 1 (<code object ClTest at 0091FCA0, file "temp.py", line 1>) 9 MAKE_FUNCTION 0 12 CALL_FUNCTION 0 15 BUILD_CLASS 16 STORE_NAME 0 (ClTest) �Esnip �E # new type class //@@ class ClTest(object): m_inStt = 3 print m_inStt def __init__(self, inAg =3): self.m_in = inAg import kcommon as kc; kc.dis() //@@@ 3 1 0 LOAD_CONST 0 ('ClTest') 3 LOAD_NAME 0 (object) 6 BUILD_TUPLE 1 9 LOAD_CONST 1 (<code object ClTest at 0091FCA0, file "temp.py", line 1>) 12 MAKE_FUNCTION 0 15 CALL_FUNCTION 0 18 BUILD_CLASS 19 STORE_NAME 1 (ClTest) �Esnip �E
�N���X�� ClTest�C�p���N���X object�C�N���X�� code object �� data stack �ɏ悹�Ă��� MAKE_FUNCTION ���s�킹��l�q�́A���錾�ł̏����Ɠ����ł��B���錾�Ƃ̈Ⴂ�� MAKE_FUNCTION �̒���Ɉ��� 0 �� CALL_FUNCTION �����s�����Ă��邱�Ƃł��B���� CALL_FUNCTION �Ăяo���ɂ���� print m_inStt �Ȃǂ����s����܂��B
�N���X���̂� virtual machine code �͎��̂悤�ɂȂ�܂��B
//@@ class ClTest: m_inStt = 3 print m_inStt def __init__(self, inAg =3): self.m_in = inAg import kcommon as kc; kc.dis() //@@@ 3 1 0 LOAD_GLOBAL 0 (__name__) 3 STORE_NAME 1 (__module__) # �N���X�� __module__ �������w�肷�� 2 6 LOAD_CONST 1 (3) 9 STORE_NAME 2 (m_inStt) 3 12 LOAD_NAME 2 (m_inStt) 15 PRINT_ITEM 16 PRINT_NEWLINE 5 17 LOAD_CONST 1 (3) 20 LOAD_CONST 2 (<code object __init__ at 0091FC60, file "temp.py", line 5>) 23 MAKE_FUNCTION 1 26 STORE_NAME 3 (__init__) �Esnip �E
�ŏ��́uLOAD_GLOBAL 0 (__name__)�v�C�uSTORE_NAME 1 (__module__)�v �̓N���X�� __module__ ������ '__main__' ��ݒ肵�Ă��܂��B���̏����͊��ł͂���܂���ł����B���̎������ STORE_FAST/LOAD_FAST �̑���� STORE_NAME/LOAD_NAME ���g�����Ƃ������Ί��̂Ƃ��Ɠ����ł��BSTORE_NAME/LOAD_NAME ���g���Ă��邱�Ƃ��u�N���X�̓��W���[���Ɗ��̗����̏������s�킹�Ă���v�ƌ������ق��� ���I�m���Ɖ���܂��B
�Ȃ� import dis; dis.dis(ClTest) �Ƃ���Ă��um_inStt = 3�v�Ȃǂ̃N���X�� python ���̋t�A�b�Z���u�����s���Ă���܂���BClTest �N���X���������ł́AClTest ���̂� code �I�u�W�F�N�g�͎g���I����Ď̂Ă��Ă��邩��ł��B���̗�̂悤�� ClTest ������Ă���Œ��� inspect �o�R�Ō��Ă��˂Ȃ�܂���B
�܂����̂悤�� class ClTest �� f_locals/f_globals ��`������ł��ƁAm_inStt, m_inStt2 �ϐ��̓��[�J���ϐ��ł���Af_locas �����Ƀ_�C�i�~�b�N�ɒlj�����Ă������Ƃ��m�F�ł��܂��B���W���[���̃g�b�v�E���x���̂Ƃ��Ƃ͈���� f_global �ϐ��ɂ͕ϐ��̒lj����s���܂���B
class ClTest: m_inStt = 3 import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_locals ) print "-----------------" import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_globals ) m_inStt2 = 5 print "----------------------------------" import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_locals ) print "-----------------" import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_globals ) //@@@ python temp.py {'__module__': '__main__', 'ins':, 'm_inStt': 3, 'pp': } ----------------- {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__'} ---------------------------------- {'__module__': '__main__', 'ins': , 'm_inStt': 3, 'm_inStt2': 5, 'pp': } ----------------- {'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__'}
�N���X�ƃ��W���[���� f_locals/f_global �̐U�镑���̈Ⴂ�� FrameObject->f_locals->ob_type �̈Ⴂ�Ő��䂵�Ă���̂��낤�Ɛ������Ă��܂��B�ł��S���̐����ł��B������̐��������Ă��鎑�����䑶�m�̕��͌䋳�����������B
���W���[����N���X�̃����o�[�̃A�N�Z�X�̗l�q�ɂ��Ē��ׂĂ݂܂��傤�B
���̂悤�� LOAD_ATTR ���߂��g���āA���W���[���̃f�[�^�v�f(�ւ̎Q��)�� TOS:Top of Stack �ɏ悹�܂��B
//@@ //@@ def testF(): import numarray as sc print sc.zeros import dis as kc; kc.dis(testF) //@@@ python temp.py 2 0 LOAD_CONST 0 (None) 3 IMPORT_NAME 0 (numarray) 6 STORE_FAST 0 (sc) 3 9 LOAD_FAST 0 (sc) 12 LOAD_ATTR 2 (zeros) 15 PRINT_ITEM 16 PRINT_NEWLINE 17 LOAD_CONST 0 (None) 20 RETURN_VALUE �Esnip �E
�v�f�������� 'zero' �� local �ϐ���O���[�o���ϐ��ł͂Ȃ��Af_code.co_names[] �ɓ����Ă���Ƃ��Ĉ����Ă��܂��B�v�f���������o������A���W���[���̃O���[�o���ϐ���N���X�̑�����������Ή����鎫�������o���̂� LOAD_GLOBAL �̂Ƃ��Ɠ����ł��Bhash ���g���č����Ɏ��o���܂��B
//@@ def testF(): import numarray as sc print sc.zeros import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_globals ) print "--------------------" import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_locals ) print "--------------------" import inspect as ins; import pprint as pp;pp.pprint(ins.stack()[0][0].f_code.co_names ) testF() //@@@ python temp.py{'__builtins__': , '__doc__': None, '__file__': 'temp.py', '__name__': '__main__', 'testF': } -------------------- {'ins': , 'pp': , 'sc': } -------------------- ('numarray', 'sc', 'zeros', 'inspect', 'ins', 'pprint', 'pp', 'stack', 'f_globals', 'f_locals', 'f_code', 'co_names')
�����ł� python �̃��X�g�ׂĂ݂܂��傤�B
Python �̃��X�g�́A�ʏ�̃R���s���[�^�E�T�C�G���X�̌��t�Ō����ΎQ�Ƃ̔z��ƌ������ق����߂��ƍl���܂��BC ����Ȃǂ̔z��Ƃ͈Ⴄ�͔̂z��ւ̒lj���}�����\�ɂȂ��Ă���_�ł��B���� python ���X�g�̗l�q�� ceval.c �\�[�X���猩�Ă݂܂��傤�B
���̃R�[�h��̂悤�� pyhon compiler �̓��X�g [1,2,3] ���^������ƁA�v�f�̒l���X�^�b�N�ɐς� BUILD_LIST ���߂��s�킹�܂��B�����̃��X�g�ւ̒lj�������� IMPLOACE_ADD ���s�킹�܂��B ���̓�̖��߂� ceval.c �\�[�X���猩�Ă݂܂��傤�B
//@@ # 07.08.14 test list lstAt = [1,2,3] print hex(id(lstAt)) lstAt += [4,5] import kcommon as kc; kc.dis() //@@@ 0x9256e8 1 0 LOAD_CONST 0 (1) 3 LOAD_CONST 1 (2) 6 LOAD_CONST 2 (3) 9 BUILD_LIST 3 12 STORE_NAME 0 (lstAt) 2 15 LOAD_NAME 1 (hex) 18 LOAD_NAME 2 (id) 21 LOAD_NAME 0 (lstAt) 24 CALL_FUNCTION 1 27 CALL_FUNCTION 1 30 PRINT_ITEM 31 PRINT_NEWLINE 3 32 LOAD_NAME 0 (lstAt) 35 LOAD_CONST 3 (4) 38 LOAD_CONST 4 (5) 41 BUILD_LIST 2 44 INPLACE_ADD 45 STORE_NAME 0 (lstAt) �Esnip �E
BUILD_LIST ���߂̃I�y�����h�̓��X�g�̃T�C�Y�ł��B���� C �\�[�X�E�R�[�h�͉��̂悤�ɂȂ��Ă��܂��BPython �̃��X�g�͎Q�Ƃ̔z��ł���A�z��v�f�̃T�C�Y�Ƃ͖��W�ɁA���X�g�v�f�̐������ŁA���X�g�ɕK�v�ȃ������E�T�C�Y�͌��܂��Ă��܂��܂��B
if (HAS_ARG(opcode)) oparg = NEXTARG(); �E �E case BUILD_LIST: # ���X�g�E�T�C�Y���̗̈�� heap �̈���m�ۂ��܂��B x = PyList_New(oparg); if (x != NULL) { # �X�^�b�N��ɂ��郊�X�g�v�f�ւ̎Q�ƒl���A�V���Ɋm�ۂ������X�g�̈�ɃR�s�[���� for (; --oparg >= 0;) { w = POP(); PyList_SET_ITEM(x, oparg, w); } PUSH(x); continue; } break;
��� C �\�[�X�����Ă���� BUILD_LIST ���߂͉��̂��Ƃ����Ă��邾���ł��B
���ꂾ�������Ă���ƁApython �̃��X�g�͔z�ƌ��������Ȃ�܂��B�ł��P�Ȃ�z��ł͒lj���}�����ł��܂���B������ǂ̂悤�ɏ������Ă��邩�́A���� INPLACE_ADD �� C �\�[�X�����邱�ƂŐ����ł��܂��B
# register PyObject *x; /* Result object -- NULL if error */ case INPLACE_ADD: w = POP(); v = TOP(); if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { /* INLINE: int + int */ register long a, b, i; a = PyInt_AS_LONG(v); b = PyInt_AS_LONG(w); i = a + b; if ((i^a) < 0 && (i^b) < 0) goto slow_iadd; x = PyInt_FromLong(i); } else if (PyString_CheckExact(v) && PyString_CheckExact(w)) { x = string_concatenate(v, w, f, next_instr); /* string_concatenate consumed the ref to v */ goto skip_decref_v; } else { # �����ł�������ł��Ȃ��Ƃ��A�Ⴆ�� list �̂Ƃ� slow_iadd: x = PyNumber_InPlaceAdd(v, w); } Py_DECREF(v); skip_decref_v: Py_DECREF(w); SET_TOP(x); if (x != NULL) continue; break;
���X�g�̒lj��ł� PyNumber_InPlaceAdd(v. w) �����Ăяo���Ă��܂��B���̊��� abstract.c �ɉ��̂悤�Ɏ�������Ă��܂��B
PyObject * PyNumber_InPlaceAdd(PyObject *v, PyObject *w) { # define NB_SLOT(x) offsetof(PyNumberMethods, x) # �uNB_�v �͂��Ԃ� New style Binary operator �̈Ӗ� PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_add), NB_SLOT(nb_add)); if (result == Py_NotImplemented) { # list �̂Ƃ��� binary operator ���Ȃ��A�����瑤�̏����ɂȂ�B PySequenceMethods *m = v->ob_type->tp_as_sequence; Py_DECREF(result); if (m != NULL) { binaryfunc f = NULL; if (HASINPLACE(v)) f = m->sq_inplace_concat; if (f == NULL) f = m->sq_concat; if (f != NULL) return (*f)(v, w); } result = binop_type_error(v, w, "+="); } return result; }
���̃\�[�X�͕ʂ̊��|�C���^���Ăяo���Ă���A���ꂾ���ł͏ڍׂȒǐՂ��ł��܂���B�ł��uconcat: concatenate �y�����z���ѕt����A����ɂȂ��v�̌��t���A��̃��X�g PyObject* v, PyObject* w �� c �� �|�C���^�ɂ��q���Ă����Ɠǂݎ��܂��BPython �̃��X�g�̃f�[�^�\�����[���R�[�h�ŕ\���Ɖ��̂悤�ɂȂ���̂Ǝv���܂��B
struct StPythonList{ PyObject* m_arPyObject # = PyObject[N] int m_indexStart; int m_indexEnd; StPythonList* m_pStPythonListNext; }
�����}������Ɖ��̂悤�ɂȂ�܂�
Python �̃��X�g����̂悤�ȃf�[�^�\���ɂȂ��Ă��邱�Ƃ́A���̃e�X�g�E�R�[�h��������t�����܂��B id(.) ���̓������E�A�h���X��Ԃ��Ă���܂��B�����胊�X�g�E�I�u�W�F�N�g�̃������z�u�A�h���X���킩��܂��B���̃e�X�g�E�R�[�h���ulstAt += [4,5] �v���s���Ă� lstAt �̔z�u�A�h���X�������ł��邱�Ƃ�����܂��B���X�g [4,5] ��lj����Ĕz��̃T�C�Y���ς�����Ƃ��A�V���Ȕz��̈���m�ۂ��ē�̃��X�g�v�f���R�s�[����̂ł͂Ȃ��A�����̃��X�g�Ƀ|�C���^���o�R���Ēlj����Ă���̂��Ɛ�������܂��B
//@@ # 07.08.14 test list lstAt = [1,2,3] print hex(id(lstAt)) lstAt += [4,5] print lstAt print hex(id(lstAt)) //@@@ 0x9256e8 [1, 2, 3, 4, 5] 0x9256e8
�ꌩ����Ɩʓ|�ȁA����ȏ���������̂́A���X�g�̃T�C�Y���傫���Ȃ����Ƃ��A��̃��X�g�̗v�f��S���R�s�[�������Ă��Ă͏������Ԃ������肷���邽�߂ł��B�|�C���^�Ōq�����킹�Ă�邱�ƂŁA�������X�g�̃R�s�[�����̔�����}���邽�߂ł��B
������ lstAt += lstAt2 �̂悤�ɂȂ邱�Ƃ�����̂ŁA���̉E���̃��X�g�ɂ��Ă̓R�s�[�E�C���X�^���X�����˂Ȃ�܂���B���̂��Ƃ́A���̃e�X�g�E�R�[�h���m�F�ł��܂��B
//@@ # 07.08.14 test list concatination time import time lstAt = [x for x in range(1000000)] lstAt2 = [x for x in range(3)] dbStartTimeAt = time.clock() lstAt += lstAt2 print time.clock() - dbStartTimeAt lstAt = [x for x in range(1000000)] lstAt2 = [x for x in range(3)] dbStartTimeAt = time.clock() lstAt2 += lstAt print time.clock() - dbStartTimeAt //@@@ 4.66137207168e-006 0.0114877698847
�u�傫�ȃ��X�g += �����ȃ��X�g�v�Ƃ����Ƃ��́A�����ȃ��X�g�̃R�s�[�E�C���X�^���X�����������܂���B�Z���������Ԃōς݂܂��B�ł��u�����ȃ��X�g += �傫�ȃ��X�g�v�Ƃ����Ƃ��́A�傫�ȃ��X�g�́E�R�s�[�E�C���X�^���X�����܂��B�����������Ԃ��K�v�ɂȂ�܂��B
�ȏ㌩�Ă����悤�� python �̃��X�g�� C ����ȂǂŌ����z��ɋ߂��̂ł����A�lj��E�}���ł̗]���ȃR�s�[�E�C���X�^���X�̐����������邽�߂Ƀ|�C���^�ł̒lj��E�}�������z��Ƃ̃����N���s���|�C���^��������f�[�^�[�\���ɂȂ��Ă��܂��B
LOAD_GLOBAL, LOAD_ATTRI �Ȃ� python interpreter �ł͕ϐ���������ɂ�鎫������̒l�̎�o�������p����܂��B���[�J���ϐ��̂Ƃ��̂悤�ɁA�R���p�C�����ɒ�܂�z��ł́A���s���ɕω�����O���[�o���ϐ���v�f������������Ȃ�����ł��B�_�C�i�~�b�N�ɑ�����ω������� interpreter �ł͕ϐ���������ɂ��l�̎��o���Ɛݒ肪�K�{�ł��E
�ł��������ɂ�鎫������̒l��o���ł͔z������A�N�Z�X���x���x���Ȃ��Ă��܂��܂��B����(map) �f�[�^����L�[������𒀎���r���Ēl�����o���Ă����̂ł́A�z��ɂ��A�N�Z�X�̉��\�{���̃A�N�Z�X���x�̒ቺ�ɂȂ��Ă��܂��܂��B������ hash ���g���Ă�邱�ƂŁA�A�N�Z�X���x�̒ቺ��{���x�̃I�[�_�[�ɗ}�����܂��B
�����ł́A�ϐ���������Ή�����l�����o���E�ݒ肷��Ƃ��Apython interpreter �� hash ���ǂ̂悤�Ɏg���Ă��邩�ׂ܂��B
�@�f�[�^�����A���S���Y���̈��ŁA�����Ƃ��|�s�����[�Ȃ��̂̈�B�����Ώۂ̃f�[ �^�����̋K���ɂ��������ăn�b�V���l�ƌĂ�鐮���ɕϊ����A�n�b�V���l���r���� �������s�Ȃ������B �@�������̂悤�ɌX�̃f�[�^���傫���ꍇ�A�f�[�^�S�̂��r���Ȃ��猟������� �����r�ɂ�����R�X�g���ߖ�ł��A�����Ɍ����ł���B�������A��������f�[�^�̑傫 ������������A�n�b�V���l�ɕϊ������Ԃ������邽�߂ɂ������Č����������Ȃ邱�� ������B �@���̃f�[�^���n�b�V���l�ɕϊ���������n�b�V�����ƌĂԂ��A���ׂẴf�[�^���� �Ȃ�n�b�V���l�����悤�ɕϊ��ł���A�T�������f�[�^�̃n�b�V���l�Ɠ����n�b�V�� �l�����f�[�^��T�����ƂŁA�T�������f�[�^�Ɠ����f�[�^�������邱�Ƃ��\�ɂȂ�B �����������ɂ͂��̂悤�ȃn�b�V������p�ӂ��邱�Ƃ͓�����߁A�n�b�V���l���d�� �����ꍇ(1�̃n�b�V���l�ɕ����̃f�[�^���G���g���[�����ꍇ)������������@��p �ӂ��Ă����K�v������B �@�n�b�V���l�̏d�������������\�I�ȕ��@�Ƃ��ẮA�d�������ꍇ�ɋĂ���n�b�V ���l�Ƀf�[�^��U�蕪����u�I�[�v���A�h���X�@�v��A�����n�b�V���l�����f�[�^��� �`���X�g�Ƃ��ĕۑ�����u���ژA���@�v�Ȃǂ�����B
python �ł� hash �l�����邱�Ƃ́A�I�u�W�F�N�g��荏���(hash ����)�A�Ή����� 32bit integer �����邱�Ƃ��Ӗ����܂��B
���������������� ��������Ȃǂ̄� hash(.) �������������������������� ��Python �������������������₷�� 32bit ���� �� ��Object �� �������������������������� ���������������� ��% map size �� ������������������������������������ ��map[]:(key,value) �ւ̎Q�Ƃ̔z�� ������������������������������������
Python �\�[�X�E�R�[�h�̕ϐ�������ɑΉ�����l�������Ɏ��o�����߂ɁA�u�I�[�v���A�h���X�@�v�ł� hash �����ȉ��̂悤�Ɏg���܂��B
���̂悤�ȏ������s�킹�� hash ���ɕK�v�ȋ@�\�� 32bit �����l�֕ϊ����邱�Ƃ����ł��B�ɒ[�Șb 0 �����Ԃ��Ȃ� hash ���ł��Amap ����ϐ���������ɑΉ����� (key,value) �y�A�����o�����Ƃ͂ł��܂��Bhash ������肭�U������l�ɂȂ�Ȃ��ƖړI�� key �ɒH�蒅���܂łɎ�Ԃ������邾���ł��B
���̂悤�� hash �l���g�����R�͔�r�̍������̂��߂ł��B�ϐ�������� key ������̓�� hash �l���قȂ邱�Ƃׂ邾���ŁA���҂̕����قȂ邱�Ƃ��ۏႳ��邩��ł��Bhash �l���������Ă��A�ϐ�������� key �����������Ƃ͌���܂��Ahash �l���قȂ�Εϐ�������� key �����قȂ邱�Ƃ͕ۏႳ���̂ŁA32 bit �����l������r���邾���A���҂��قȂ邱�Ƃ��m�F�ł��Ă��܂��܂��B'abcdefgX' �� 'abcdefgY' ��̕�������ŏ��̕��� a ���璀����Ԃ������Ē��ׂ�K�v���Ȃ�����ł��B
python �ł̓^�v���^���X�g�^���������l�╶����Ɠ��l�Ȋ�{�v�f�ł���A�I�u�W�F�N�g�� hashable �ł��邩�ۂ����s�ʂ���܂��B���� hashable �ł��邱�Ƃ����X�g�ƃ^�v���̕����Ő��������Ƃ��ύX�ł��Ȃ����ƁFimutable �Ɠ����ł��邩�̂悤�ɐ�������邱�Ƃ����荬���������܂��BPython �� hashable �ł���Ƃ� hash ��������邱�Ƃł��Bimutable �̈Ӗ��ł͂���܂���B
�������ɁA���X�g�⎫���͕ύX�ł��A�܂� hashable �ł͂���܂���B����ɔ�r���āu���l�� 1�v��u������'abc'�v�u�^�v�� (1,2,3)�v�Ȃǂ͕ύX�ł����A�܂� hashable �ł��B
�ł����̃R�[�h��ł�����悤�� class �� class �C���X�^���X�͕ύX�\�ł���Ȃ��� hashable �ł��B�^�v���ł����X�g��v�f�ɂ���� hashable �ł͂���܂���B
//@@ class ClTest:pass clAt = ClTest() print hash(ClTest) print hash(clAt) print hash( (1,2,[1,2,3]) ) //@@@ 9562512 9590424 Traceback (most recent call last): File "temp.py", line 6, in ? print hash( (1,2,[1,2,3]) ) TypeError: list objects are unhashable
hash ������̓I�ɂǂ�ȕ��Ɍv�Z���Ă���̂����ׂĂ݂��̂ł����A�r���܂ł����킩��܂���ł����B������ hash �l�͐����l���̂��̂ł����B�N���X��N���X�E�C���X�^���X�� hash �l�� id �l�Ɠ����ł����B�������E�A�h���X�ł����B
//@@ class ClTest:pass clAt = ClTest() print "----------- id --------------" print hex(id(128)) print hex(id(ClTest)) print hex(id(clAt)) print "---------- hash -------------" print hex(hash(128)) print hex(hash(ClTest)) print hex(hash(clAt)) //@@@ ----------- id -------------- 0x953cc4 0x91e9c0 0x925698 ---------- hash ------------- 0x80 0x91e9c0 0x925698
�������^�v���Ȃǂ͐荏��� 32bit �����ɕϊ����Ă���͉̂���̂ł����A���̋�̓I�Ȑ荏�ݕ��܂ł͒͂߂܂���ł����B�䑶�m�̕��͌䋳�����������B
�ł� python �ɂ����� hash �l�́uhash �l���قȂ�Ƃ��́A�قȂ����I�u�W�F�N�g�ł���v������������Ή��ł��\���܂���B�ɒ[�Șb��� 0 ��Ԃ��悤�� hash ���ł� python �͓����܂��B���삪�x���Ȃ邾���ł��B
�t�� hash �l�������ł��邩��ƌ����Ď����L�[�Ƃ��Ă͏d�����܂���B���̃R�[�h�Ⴊ����������܂��B
//@@ print hex(hash(2)) print hex(hash(2**32+1)) dctAt={} dctAt[2]="abc" dctAt[2**32+1]="xyz" print dctAt //@@@ 0x2 0x2 {2: 'abc', 4294967297L: 'xyz'}
�����̏���������Ă������߁A�����g�����p�ȉ�蓹��������ꂽ�̂ŏ����Ă����܂��B
�����ł� python �� generator �� python virtual machine �̃��x���Œ��ׂČ��܂��傤�Bgenerator ���̂킩��ɂ����_�͉��̓�ł��B
�ȉ��A��̓�̗l�q�����ڍׂɒ��ׂĂ݂܂��傤�B
�����ł� python interpreter �� generatorObject ������ڍׂȗl�q��`������ł݂܂��傤�B
���� python virtual machine code �����Ă��邾���ł́Agenerator �̗l�q�͂��܂茩���Ă��܂���B���̃R�[�h�� ���X�g�Frange(3) �̑���� generator:xrange(3) �ɂ��Ă� range �� xrange �ɕς�邾���ł��B
//@@ #for x in xrange(3): for x in range(3): print x import kcommon as kc; kc.dis() //@@@ C:\my\vc7\mtCm>python temp.py 0 1 2 2 0 SETUP_LOOP 25 (to 28) 3 LOAD_NAME 0 (range) 6 LOAD_CONST 0 (3) 9 CALL_FUNCTION 1 12 GET_ITER >> 13 FOR_ITER 11 (to 27) 16 STORE_NAME 1 (x) 3 19 LOAD_NAME 1 (x) 22 PRINT_ITEM 23 PRINT_NEWLINE 24 JUMP_ABSOLUTE 13 >> 27 POP_BLOCK
GET_ITER ���߂ɂ��ATOS �ɂ���V�[�P���X(���̏ꍇ�� range(3) ����������X�g)�œ����C�^���[�^����� TOS(Top Of Stack) �ɏ悹�܂��BFOR_ITER �ɂ�� TOS �ɂ����� iterator ����l�� stack �ɐς܂��܂��B���� TOS ��̒l�����[�J���ϐ� x �ɑ���������ƂɁA���[�v�������s���Ă����܂��Bxrange(3) ���g�����Ƃ��́A����� iteratorObject �����X�g:[1,2,3] �ł͂Ȃ� xrange(3) �ɂ���č������̂ɕς�邾���ł��B
9 CALL_FUNCTION �̎��s�� 12 GET_ITER �̎��s�� 12 GET_ITER �̎��s�� ���������������������� TOS�� 1 �� �������������������� ���������������������� ���������������������� TOS��[1,2,3] �ւ̎Q�Ƅ� TOS��intrator �ւ̎Q�� ���� iteratorObject ��intrator �ւ̎Q�� �� �������������������� ���������������������� ([1,2,3]) ���������������������� �� �� �� �� �� �� �������������������� ����������������������or iteratorObjet ���������������������� (xrange(3))
generator ���� python virtual machine code �����Ă� yield ���߂��}�������ȊO�͕��ʂ̊��ƈႢ�͌����܂���B
//@@ # 07.08.21 test generatro def testGnrt(): yield 1 return for x in testGnrt(): print x import dis; dis.dis(testGnrt) //@@@ python temp.py 1 3 0 LOAD_CONST 1 (1) 3 YIELD_VALUE 4 4 LOAD_CONST 0 (None) 7 RETURN_VALUE
Python interpreter �ɂƂ��āA generator ���ƕ��ʂ̊��̈Ⴂ�� CodeObject �� co_flags �� CO_GENERATOR:0x0020 �t���O�E�r�b�g�������Ă��邩�ۂ��̈Ⴂ���d�v�ł��B���̂悤�ɁA���̃t���O�������Ă��邱�Ƃ��m�F�ł��܂��B
//@@ # 07.08.21 test generatro def testGnrt(): yield 1 return gnrtAt = testGnrt() import inspect as ins;print hex(dict(ins.getmembers(testGnrt.func_code))['co_flags']) //@@@ 0x63 //@@ # 07.08.21 test generatro def testGnrt(): #yield 1 return gnrtAt = testGnrt() import inspect as ins;print hex(dict(ins.getmembers(testGnrt.func_code))['co_flags']) //@@@ 0x43
Python compiler �͊��� yield �����܂ނ��Ƃ����o����ƁA���� CodeObject �� co_flags �� CO_GENERATOR �t���O�� 1 �ɃZ�b�g���܂��B���ꂪ���� CALL_FUNCTION �Ŋ����Ăяo���Ă����Ƃ��A�Ăяo���ꂽ���̎��s���Ȃ킿 PyEval_EvalFrame(.) ���Ăяo�����O�ŁA generator �I�u�W�F�N�g�����Ė߂�l�Ƃ��A�Ăяo���ꂽ�������s������ return ���܂��B���̕����� C �\�[�X�E�R�[�h�����Ɏ����܂��B
case CALL_FUNCTION �� static PyObject * call_function(PyObject ***pp_stack, int oparg) ��DLL �����ۂ��ŏ�����U�蕪���܂� static PyObject * fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) ��# CO_GENERATOR �t���O�������Ă���Ƃ��̏������lj��ōs���܂� PyObject * PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, { �E �E if (co->co_flags & CO_GENERATOR) { /* Don't need to keep the reference to f_back, it will be set * when the generator is resumed. */ Py_XDECREF(f->f_back); f->f_back = NULL; PCALL(PCALL_GENERATOR); /* Create a new generator that owns the ready to run frame * and return that as the value. */ return PyGen_New(f); } retval = PyEval_EvalFrame(f); } ��# python machine code �̎��s PyObject * PyEval_EvalFrame(PyFrameObject *f)
���̂悤�� CodeObject.co_flags �� CO_GENERATOR �������Ă��邱�Ƃ��Agenerator �����Ăяo����generator ���̎��s���O�̒i�K�̏�Ԃ܂ŏ���������ԂŁA�Ⴆ�� FrameObject ���p�ӂ�����Ԃ� generatorObject ��Ԃ��܂��B���ꂪ generator �����Ăяo�����Ƃ��ɍs���邱�Ƃł��B
generator ���� yield ���͊��̎��s�𒆒f���܂��BgeneratorObject.next() ���\�b�h�́A���f���ꂽ�������ĊJ���܂��B
Python �� �� FunctionObject + FrameObject FrameObject �� Local �ϐ� + int f_lasti /* Last instruction if called */ + etc
yield ���� FrameObject.f_lasti �����Ɏ��s���� python virtual machine code �̒l�ɂ��Ė߂�܂��BgeneratorObject.next() �����s���ꂽ�� FrameObject.f_lasti �̈ʒu������s���ĊJ���܂��B���[�J���ϐ��� generatorObject ���ɐ݂����� FrameObject ���ɕێ����������Ă��܂��B
���̈Ӗ��� python �̊�== FunctionObject + FrameObject �� generatorObject �ɂ��邱�ƂŎ��s�r���̏�Ԃ�e�ՂɎ����ł��܂��B������ rane(1000000) �̂悤�ȑ傫�ȃ��X�g�̐����������邽�߂ɁAxrange(1000000) �� generatorObject �̎��s�r���̏�ԂŒl��Ԃ����Ă��܂��B
generatorObject ���A���̎��s�r���̏�ԂŒ��f�E�ĊJ�ł��邱�Ƃ� co-operative thread �̊�{�@�\�����邱�Ƃ��Ӗ����܂��BFrameObject �� thread �̃R���e�L�X�g�ɂł��邩��ł��Bwait(delayAg=-1) �� restart() ���\�b�h��lj����Ă��� co-operative �� thread �������ł��Ă��܂��B
��ʂɂ� co-operative �� thread ��� pre-emptive �� thread �̂ق������@�\���Ƃ̌�������邪�A�命���̃��[�U�[�ɂƂ��Ă� co-operative �� thread �̂ق��������₷���Bpre-emptive �� thread �̓R���e�L�X�g�E�X�C�b�`���ǂ�ȃ^�C�~���O�Ŕ������Ă��悢�悤�Ƀv���O�������Ȃ���Ȃ�Ȃ�����ł��Btest and set �̋��Ԃɔ�������p�x�̏��Ȃ�����ɂ����o�O�̊댯����������ł��B(����ɂ��ẮA���� thread �̐߂ŁA���ڂ����l�@���܂��B)
Pre-emptive �� thread ���K�v�ɂȂ邱�Ƃ�����܂��B mili second �ȉ��̃N���e�B�J���ȃ^�C�~���O��ۏႹ�˂Ȃ�Ȃ��Ƃ��� thread �ɗD�揇�ʂ�ݒ肵�A���� thead �̎��s�𒆒f�����ėD�悳����ׂ� thead �����s���˂Ȃ�܂���B�f�o�C�X�E�h���C�o�� multi thread �L�q������Ȃ�A�����̂��� pre-emptive �� thread ���K�v�ɂȂ�ł��傤�B
�ł� Windows/Linux �Ƃ������A�v���P�[�V������ multi thread �L�q������Ƃ��� mili second �̂悤�ȃN���e�B�J���ȃ^�C�~���O���v������邱�Ƃ͂���܂���B����� OS �̊Ǘ��̉��œ����A�v���P�[�V�����E�v���O�����ł͈�b�̉������x�̕ۏႳ������Ȃ��̂����ʂł��B�C���[�W���ڂ� web page ���J���Ă���̂ƕ��s���ē��삷��A�v���P�[�V��������b�̓���x����Ă����傤������܂���B���̂悤�ȃA�v���P�[�V�����ł� multi thread �L�q�ł� co-operative �� thread ���g���ׂ��ł��B
���[�U�[���R���e�L�X�g�E�X�C�b�`�̃^�C�~���O���I�ɋL�q���� co-operative �� thread �Ȃ�Atest and set �̋��Ԃɔ�������o�O���������܂���BLock �� Critical Section �Ȃǂ��g�����ƂȂ��������L�q�ł��܂��BCo-operative �� thread �ł� test and set �̋��Ԃ̖�肪�������Ȃ��̂ŕ����L�q���e�ՂɂȂ�܂��B
���̂悤�� generatorObject ���g���� VrfyYThrd ���W���[��������Ă��܂��B�߁X���\���܂��B���̂Ƃ��͗V��ł݂Ă��������B
�����ł� python �� thread �Œ��ӂ��ׂ��_�Ƒ�ɂ��� python virtual machine �̃��x���ōl���܂��BPython �ł� thread �������@�ɂ��Ē��ׂ����ƁApython thread �̖��_�ɂ��Č������܂��B
Python �� thread ����́AGiant Lock �t���O���Q�Ƃ��Ȃ��� 100 python virtual machin instruction ���ƂɎ��s���� OS thread ���ւ��邱�ƂŎ������Ă��܂��B
Python �̊��� FrameObject �� FunctionObject ��g�ݍ��킹�����̂�Ώ̂ɁA���� co_code ������ PyEval_EvalFrame(.) �Œ������s�����Ă��܂����B�ł����� python virtual machine code �𒀎����s���Ă��� PyEval_EvalFrame(.) ���� OS thread ��ŕ���Ɏ��s�����Ă����Ă�邱�ƂŁApython �� multi thread �������ł��܂��BOS thread ��ł̕�����s�ɂ�� multi CPU �ɂ�������s���\�ɂȂ�܂��B
FrameObject �� FrameObject ���E�E /* Last instruction if called */ �� /* Last instruction if called */ ���E�E ����int f_lasti; �� ����int f_lasti; �� �� �E �� �� �E �� �� FunctionObjct �� �� FunctionObjct �� �� CodeObject �� �� CodeObject �� �� co_code �� �� co_code �� �� 0 LOAD_CONST �� �� 0 LOAD_FAST �� �� 3 UNPACK_SEQUENCE �� �� 3 LOAD_FAST �� ������������ 6 STORE_NAME �� �� 6 BINARY_ADD �� 9 STORE_NAME �� ������������ 7 STORE_FAST �� 12 STORE_NAME �� 10 LOAD_CONST �� �E �� �E �� �E �� �E �� �� �� �� �� PyEval_EvalFrame(FrameObject* f) �� PyEval_EvalFrame(FrameObject* f) �� { �� { �� �E �� �E �� �E �� �E �� if PyDECREF(x){ �� <------- context switch -----> Py_INCREF(x) �� delete(x) �� } �� �� �E �� �E �� �E �� �E �� } �� } ���E�E
�ł� PyEval_EvalFrame(.) ���� reentrant �ł͂���܂���B�Ⴆ�Ώ�̂悤�ɕ����� thread �ŋ��p����� python object x �� reference count �� decrement ���� python object ���������悤�Ƃ���u�Ԃ� context switch ���������āA�ʂ� thread �� reference count �� increment ������A���݂�������͂��� pytho object x �͂Ȃ��Ȃ��Ă��܂��܂��BPyEval_EvalFrame(.) ���� reentrant �łȂ����Ƃɂ����͔�������ӏ������ɂ��������݂��Ă��܂��B
Reentrant �łȂ� PyEval_EvalFrame(.) �������Ɏ��s�����邽�߂� PyEval_EvalFrame(.) ���̒��� context switch ���s�킹��ꏊ���A���ߏ������[�v�̍ŏ��̉ӏ��Ɍ��肵�Ă��܂��B�Aceval.c �\�[�X�̉��̕����� python thread �� context switch �^�C�~���O�𐧌䂷�� C �v���O�����ł��B
# Giant Interpreter Lock static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */ int _Py_CheckInterval = 100; volatile int _Py_Ticker = 100; PyObject * PyEval_EvalFrame(PyFrameObject *f) { PyThreadState *tstate = PyThreadState_GET(); �E �E tstate->frame = f; �E �E for (;;) { if (--_Py_Ticker < 0) { �E �E _Py_Ticker = _Py_CheckInterval; �E �E if (interpreter_lock) { /* Give another thread a chance */ if (PyThreadState_Swap(NULL) != tstate) Py_FatalError("ceval: tstate mix-up"); PyThread_release_lock(interpreter_lock); # Giant Lock ���O�����̂ŁA���� # PyEval_EvalFrame(.) �������s�ł��� /* Other threads may run now */ PyThread_acquire_lock(interpreter_lock, 1); if (PyThreadState_Swap(tstate) != NULL) Py_FatalError("ceval: orphan tstate"); /* Check for thread interrupts */ if (tstate->async_exc != NULL) { x = tstate->async_exc; tstate->async_exc = NULL; PyErr_SetNone(x); Py_DECREF(x); why = WHY_EXCEPTION; goto on_error; } } �E �E �E switch (opcode) { �E �E } } }
/* Other threads may run now */ �̉ӏ��ŁAGiant Lock:OS �� thread ��ւ����b�N���O���A�ʂ� PyEval_EvalFrame(.) ���Ɏ��s���ڂ���悤�ɂ��Ă��܂��BContext switch ������̂��A���̈ʒu�����Ɍ��肷�邱�ƂŁAreentrant �łȂ� PyEval_EvalFrame(.) ���̕�����s���\�ɂ��Ă��܂��B
_PyTicker �͖��߂̏����𐔂��� static �ȕϐ��ł��B��� python ���߂��Ƃ� PyEval_EvalFrame(.) �����ւ��Ă��Ă� thread ��ւ��̂��߂� OS CPU �������Ԃ������ python interpretor �̎��s���x���Ȃ��Ă��܂��̂ŁA _Py_Ticker�F100 �Ƃ� PyEval_EvalFrame(.) �����ւ��Ă��܂��B
���̐ݒ�͉��̂悤�� python �R�[�h����m�F�ł��܂��B
//@@ # 07.08.22 test getcheckinterval() import sys print sys.getcheckinterval() //@@@ 100
I/O �����̍Œ��Ȃ� PyEval_EvalFrame(.) �����ւ��Ă͂܂����^�C�~���O������܂��B���̂Ƃ��̂��ɂ� Giant Lock �t���O�Finterpreter_lock ���݂����Ă��܂��Binterpreter_lock == 0 �ł��邩����APyEval_EvalFrame(.) ���̐�ւ��͔������܂���B�Ȃ� interpreter_lock �� threading.Lock() �Ƃ͕ʕ��ł��B���[�U�[�� interpreter_lock �𗘗p����Ƃ����� C API ���g�����Ƃ��� C ���ŋL�q�������� threadsafe ��ۏႵ�����Ƃ��ȂǂɌ����܂��B
Python �� thread �� pre-emptive �ł��B�O�̐߂ŏq�ׂ��悤�� python �� multi thread �� _Py_Ticker�F100 ���߂��Ƃ� thead ���ւ��܂��B���[�U�[�ɂ� thread �̂ǂ��� context switch ���������邩����܂���BPython Program �̔C�ӂ̉ӏ��� context switch �����������܂��B�v���O�����̗��ꎟ��ł��B100 ���߂��Ƃɕʂ� thread ���ւ���l�q�� time slice �ɂ�� thread ��ւ��Ɏ��Ă��܂��B
����ŕ����� thread �̊Ԃɂ͋��ʕϐ������݂��邱�Ƃ���������܂��BThread �̂ǂ��ł� context switch �����������邱�ƂƋ��ʕϐ������݂��邱�Ƃ��g�ݍ��킳�邱�ƂŁA multi thread ���L�̃o�O�����荞��ł��܂��B�Č����̂Ȃ������p�x�̏��Ȃ����炵���o�O�ł��B
�ȉ��ł́A���� multi thread ���L�̃o�O��P����Ō������܂��B����� python �� random ���W���[���� ����̓I�Ȍ`�ōČ������܂��B
Pre-emptive �� multi thread programming �ł͕����� thread ������ăA�N�Z�X�����ϐ����듮��������N�����܂��B���̗�ōl���Ă݂܂��傤�B
denominatorGlb | +-------------+-----------------+---------------- �E�E�E�E | | def thread_1(): def thread_2(): �E�E�E�E �E �E �E �E denominatorGlb = 3 �E �E �E �E �E �E ��- context switch �� denominatorGlb = 0 someAt /= denominatorGlb someAt *= denominatorGlb �E �E �E �E
��̃R�[�h��� denominatorGlb �� thread_1 �� thread_2 �̗����œǂݏ�������Ă��܂��Bthead_1 �� demoninatorGlb = 3 �Ɛݒ肵�Ă� someAt /= denominatorGlb �����s����Ƃ��� denominatorGlb �� 3 �̒l��ۂ��Ă���ۏႪ����܂���B someAt /= denominatorGlb �����s����܂ł� context switch ���������āAthread_2() �����s���� denominatorGlb �� 0 �ɏ���������Ă���\��������܂��B
���̃o�O�͍L��I�ł��B�������ꂽ�Ƃ���:thread_2() �̓���������ł��܂��Bthread_1() ���������Ă���ƁAdemoninatorGlb = 3 �Ɛݒ肵�Ă���̂ŁA someAt /= denominatorGlb �͐���Ɏ��s�����悤�Ɍ����Ă��܂��܂��B���ۂɂ��A��������s����܂ł̊Ԃ� context switch ���������Ȃ���A���Ȃ킿�啔���̃^�C�~���O�ł͐���ɓ��삵�Ă��܂��܂��B�o�O����������̂̓N���e�B�J���ȃ^�C�~���O�Ɍ����܂��B�������A���̃o�O�� thread_1() �̃R�[�h�߂Ă��邾���ł͌��������߂܂���B��������Ă��邩������ȁA�ʂ̃t�@�C���ɂ��邩������Ȃ� thread_2() �̓������ɂ���Č듮��ƂȂ�܂��B
denominatorGlb | +-------------+-------------------------+---------------- �E�E�E�E | | def thread_1(): def thread_2(): �E�E�E�E �E �E �E �E denominatorGlb = 3 �E �E �E �E �E if denominatorGlb != 0: ��- context switch --------�� denominatorGlb = 0 someAt /= denominatorGlb someAt *= denominatorGlb �E �E �E �E
��̂悤�ɁA����Z������O�Ɂuif denominatorGlb != 0:�v���肵�Ă���Ă���ɂ͂Ȃ�܂���B�uif denominatorGlb != 0:�v����̌�ɃR���e�L�X�g�E�X�C�b�`�����������瓯���o�O���������邩��ł��B�������� if ����̒lj��ɂ��o�O�̔����p�x�͏��Ȃ��Ȃ�܂��B�ł��o�O�̍Č����������Ȃ邱�Ƃł�����A��萫���̈����o�O�ɂȂ��Ă��܂��܂��B
Multi thread programming �ł̃o�O�͍Č����������A�܂������p�x�����Ȃ����߂ɖ��ȃo�O�ƂȂ肪���ł��BdemoninatorGlb = 3 �Ɛݒ肵�Ă���̂ŁA someAt /= denominatorGlb �����s����܂ł̊Ԃ� context switch ���������Ȃ���ΐ���ɓ��삵�Ă��܂�����ł��B
Multi thread programming �ŋ��ʕϐ����m���ɑ��݂��Ȃ��悤�Ƀv���O�������邱�Ƃ͊ȒP�ł͂���܂���BPython �ł� import �������W���[������ global �ϐ������݂����邩��ł��BThreadsafe ���W���[���ł�����ʕϐ��ɂȂ肤��ϐ��݂͐��܂���B�ł� python �� threadsafe �ł���Ɩ������Ă��郂�W���[���͖w�ǂ���܂���B
���ʕϐ��������I�ɔ������Ȃ����Ƃ���������܂��B���̂悤�Ɉ��� LAN �v�����^�ɕ����� thread ����܂Ƃ܂�̕��͂��o�͂��Ă����Ԃ��l���܂��傤�Bthread_1() �����͏o�͒��� thread_2() �� LAN �v�����^�ɏo�͂ł��܂���Bthread_2() �� LAN �v�����^���Ă���Ƃ������o�͂ł��܂���B��Ɉ�� thread �݂̂� LAN �v�����^�ɏo�͂��Ă��邱�Ƃ�ۏႷ�邽�߂ɂ� thread �Ԃŋ��ʂ��ēǂݏ���������ԕϐ����K�v�ɂȂ�܂��B
������Ȃ����\�[�X���� thread ���g���Ƃ��͔r���I�ɓ��삹��������܂���B��̃��\�[�X���̃X���b�h�Ŕr���I�Ɏg���ɂ́A���̃X���b�h�ɋ��ʂ��� global �ȏ�ԕϐ����ǂ����Ă��K�v�ɂȂ�܂��B���̂悤�� blUsingGlb ��݂��� blUsingGlb == False �̎��� LAN �v�����^���g���悤�ɂ���Ηǂ������Ɍ����܂��BThread �� LAN �v�����^�ɏo�͂���܂��� blUsingGlb = True ��Ԃɂ��ALAN �v�����^ �ɏo�͂���̂����������Ղ� blUsingGlb = False �ɖ߂��Ă��Δr���I�ɓ��������ł��B
LAN_Printer blUsingGlb = False | +-------------+-----------------+---------------- �E�E�E�E | | def thread_1(): def thread_2(): �E�E�E�E �E �E �E �E if blUsingGlb == False: if blUsingGlb == False: ��- context switch �� blUsingGlb = True: blUsingGlb == True: for strAt open(fileName): for strAt open(fileName): print strAt, print strAt, blUsingGlb = False: blUsingGlb == False: �E �E �E �E
�ꌩ�����������ƁA����ŗǂ������Ɏv���Ă��܂��܂��B�ł��A����ł͌듮�삵�܂��B�������v���O�����̌듮�삷��^�C�~���O�������܂��B if blUsingGlb == False �� test �����Ă��� blUsingGlb = True �̒l�� set ����܂ł̊Ԃ� context switch ���������āA�Ȃ����A���� context switch �ŕʂ� thread �� if blUsingGlb == False �`�F�b�N���s���N���e�B�J���ȃ^�C�~���O�̂Ƃ��Ɍ����āALAN �v�����^�ɓ����ɏo�͂���듮�삪�������܂��B���ꂪ Multi thread programming �ɂ�����utest and set �̋��Ԃ̖��v�ł��B�啔���̃^�C�~���O�ł͐���ɓ��삵�Ă��܂����߁A�Č����̂Ȃ��o�O�ƂȂ錙�炵�����ł��B
���́utest and set �̋��Ԃ̖��v������邽�߂� threading.Lock() ���p�ӂ���Ă��܂��B���̂悤�Ɏg���܂��B
LAN_Printer lockGlb = threading.Lock() | +-------------+-----------------+---------------- �E�E�E�E | | def thread_1(): def thread_2(): �E�E�E�E �E �E �E �E lockGlb.acquire() lockGlb.acquire() for strAt open(fileName): for strAt open(fileName): print strAt, print strAt, lockGlb.release() lockGlb.release() �E �E �E �E
Lock �I�u�W�F�N�g lockGlb �ɂ��ẮALock() �̍Œ��ɂ́utest and set �̋��Ԃ̖��v���������Ȃ��悤�� context switch ���֎~����Ȃǂ̑�����ꏈ���n�̒��ōs���Ă��܂��B
���������� thread ���p�ϐ��E���p�I�u�W�F�N�g�ɂ��āAthreading.Lock() �Ȃǂ��g���ăv���O���}�[���r���I�ł��邱�Ƃ�ۏႹ�˂Ȃ�܂���B�ł����l����������W���[���̒��ɔ������� thread ���p�ϐ��܂ł͒��ӂ���܂���B
���ۂ� multi thread programming �ň�Ԓ��ӂ��Ȃ���Ȃ�Ȃ��̂��A���̈ꌩ�����Ă��܂��� �utest and set �̋��Ԃ̖��v�ł��B�N���e�B�J���ȃ^�C�~���O�������ē��삵�Ă��܂�����ł��B�v���O�������̂� multi thread programming �łȂ���ΐ������v���O�����ł��BContext switch �̂��Ƃ��ӎ����Ă��Ȃ�����A���L�q���Ă��܂��v���O�����ł��B���ʂ̊��Ăяo���ł͕p�ɂɍs���Ă���L�q������ł��B�������f�������łȂ���Ă����� �utest and set �̋��Ԃ̖��v�̔����ӏ��ł���Ƃ����ӎ�����̂�����Ȃ�܂��B
somModule someModule.global �ϐ� 1 someModule.global �ϐ� 2 �E �E | +-------------+-----------------+---------------- �E�E�E�E | | def thread_1(): def thread_2(): �E�E�E�E �E �E �E �E import someModule import someModule if someModule.test(): if someModule.test(): someModule.set() someModule.set() �E �E �E �E
�utest and set �̋��Ԃ̖��v�̌��炵���́A�o�O�̔������N���e�B�J���ȃ^�C�~���O�Ɍ����邱�Ƃł��B�ʏ�̃v���O�����E�e�X�g�ł͌��������o�O�ɂȂ�₷�����Ƃł��B�啔���̃^�C�~���O�ł�����ɓ��삵�Ă��܂����Ƃł��B��K�͂ȃv���O�����ɂ�����Č����̂Ȃ������p�x�̏��Ȃ��o�O�̌��炵���͐E�ƃv���O���}�[�Ȃ�ΐg�ɂ��݂ė������Ă��炦��͂��ł��B�s��ɏo�Ă���̌�q�̂Ƃ���ňꃖ���Ɉ����x�̕p�x�Ŕ�������A�������z�̌��Ⴂ�Ȃǂ̒v���I�ȃo�O�̕|���𗝉����Ă��炦��͂��ł��B
Co-operative �� thread �Ȃ�A�N���e�B�J���ȃ^�C�~���O�Ɍ���ꂽ�o�O�����荞�݂܂���BContext switch ���s����̂́Await(.) �� yield �Ȃǂ̃R���e�L�X�g�E�X�C�b�`����������▽�߂����s�����Ƃ��Ɍ����邩��ł��BCo-operative �� thread �ł̓v���O���}�[�� context switch �̃^�C�~���O���I�ɋL�q���邩��ł��B���ʕϐ��ɂ��o�O�̖��͎c��܂����A��̂悤�Ȏ��O�̔r�����䂾���őΏ��ł��܂��Bpre-emptive �� thread �ł̃o�O�ɔ�r����A�o�O�̕p�x�E�Č����̖ʂőf���̗ǂ��o�O�Ɏ��܂�܂��B������ co-operative �� thread �̗��p���l����ׂ����Ǝ咣���܂��B
Python �� random ���W���[�����ɁAthread �ԋ��ʕϐ��̖��� ����̓I�Ɍ������Ă݂܂��傤�Brandom ���W���[���� python ���W���[���ł͒����� threadsafe �L���Ă��܂��B
python -m pydoc random �E �E * The random() method is implemented in C, executes in a single Python step, and is, therefore, threadsafe. �E
�ʏ�� random ���W���[�������̂悤�Ɏg���܂��B
//@@ # coding=shift_jis # 06.10.29 test random import random as rm print rm.seed(1) # �Č������K�v�ȂƂ���(seed)��ݒ肷�� print rm.random() # ��� random value print [rm.random() for x in range(10)] #print [rm.random() in range(10)] # [False] �ɂȂ� //@@@ 0.286764866026 [0.9478009373832299, 0.083293806704341389, 0.69287751155037047, 0.11174129451311121 , 0.94066583365119105, 0.075509802509286628, 0.48949937014030143, 0.65659243274936629 , 0.92908348489143999, 0.8888168647683683]
��̂悤�ɒP���ȋL�q���ł���̂� random ���W���[���� Random �N���X�̃C���X�^���X�����W���[���� global �ϐ� _inst �Ƃ��č���Ă��邩��ł��Brandom ���W���[���� seed ���̃��x���ɑΉ��������Ă���̂� _inst.seed �� callable �Ȋ��I�u�W�F�N�g������ł��B
>type C:\lng\python24\Lib\random.py �E �E _inst = Random() seed = _inst.seed �E �E getrandbits = _inst.getrandbits �E
random ���W���[������ _inst �O���[�o���ϐ����g���Ă��邽�߁A���̂悤�ɕ��ʂ� random ���W���[���̎g������ multi thread programming �ł��s���Ă��܂��ƁAthread �ԋ��ʕϐ� random._inst �� random ���W���[�������Ŏg���Ă��܂��܂��B���̂悤�� thread_1() �� rm.seed(1) �ɐݒ肵���̂ɁAthread_2() �������� rm.seed(2) �ɕύX����Ă��܂��܂��B
import random as rm def thread_1(): def thread_2(): �E�E�E�E �E �E �E �E rm.seed(1) rm.seed(3) valeuAt = rm.random() valeuAt = rm.random() �E �E �E �E
Threadsafe �ȃv���O�������������߂ɂ́Arandom._inst ���g��Ȃ�������������K�v������܂��B���̂悤�ɏ����K�v������܂��BThread �ԋ��ʕϐ��������Ȃ��������ɂ���K�v������܂��B
import random as rm def thread_1(): def thread_2(): �E�E�E�E �E �E �E �E clRandomAt = rm.Random() clRandomAt = rm.Random() clRandomAt.seed(1) clRandomAt.seed(3) valeuAt = clRandomAt.random() valeuAt = clRandomAt.random() �E �E �E �E
Threadsafe ���������Ă��� random ���W���[���ł��� ���̃\�[�X��ǂ����x���ŗ������Ă��Ȃ��� thread �ԋ��ʕϐ������ꍞ��ł��܂��܂��BThreadsafe �ł͂Ȃ��Ȃ��Ă��܂��܂��BThreadsafe ���l�����Ă��Ȃ���ʂ̃��W���[���𗘗p�����Ƃ��A���� threadsafe ��ۏႷ��ӔC�͈�ʃ��W���[���̃��[�U�[�ɂ���܂��B�v���O���}�[�͗��p���W���[���̃\�[�X��S�Ēǂ��� threadsafe �ł��邱�Ƃ��m�F������łȂ���� threadsafe �ȃv���O�����������܂���B���p���W���[�����Ăяo���Ă����̃��W���[���܂Ŋ܂߂��\�[�X�m�F���K�v�ɂȂ�̂ŁA���p���W���[���� threadsafe ��ۏႷ��̂͌����ɂ͕s�\�ɂȂ邱�Ƃ������Ȃ�܂��B
���� python �� thread/threading ���W���[���� thread safe �ȃv���O������������͔̂��Ɍ�����Ǝ咣���܂��B1000 �s����K�͂� thread/threading ���g�����Athread safe �Ŏ��p�I�Ӗ��̂��� ���� thread ���Q�̍쐬�͐_�Ƃɋ߂��Ǝ咣���܂��B
decorator �\���� inspect �� disassemble ���g�����ق��� �悭����܂��B���t�ł����璚�J�ɐ������Ă������O�d�Ƀl�X�g���闝�R�͊ȒP�ɂ͗����ł��Ȃ��ł��傤�B�t�� �����܂ł� disassemble/inspec/virtual machine code �������Ă���Ȃ�A�������g���� python �� decorator �\���R�[�h��ǐՂ��邱�ƂŁA@decorator �\���̈Ӗ������S�ɗ����ł��܂��B
Python �̃f�R���[�^�[�\�� @dcrt �͊��̒u�������ƁAclosure �̐����̓�̈Ӗ�������܂��B���̓�̏ڍׂ��ȉ��`������ōs���܂��B
Python �̃f�R���[�^�[�\�������̒u�������ł��邱�Ƃ́A���̃R�[�h���f���o�� disassemble ���ʂ����Ă��Έ�ڗđR�ł��B
//@@ def dcrtF(fnAg): print "Now in dcrtF(.):",fnAg inFreeAt = 1 def innerF(objAg): print inFreeAt import time print "Now innerF(.)", objAg dbStartTimeAt = time.clock() fnAg(objAg) print time.clock() - dbStartTimeAt return innerF @dcrtF def testF():pass import kcommon as kc;kc.dis() //@@@ Now in dcrtF(.):1 0 LOAD_CONST 0 (<code object dcrtF at 0091FD20, file "temp.py", line 1>) 3 MAKE_FUNCTION 0 6 STORE_NAME 0 (dcrtF) 16 9 LOAD_NAME 0 (dcrtF) # testF() ���I�u�W�F�N�g���� data stack �ɏ悹�� 12 LOAD_CONST 1 (<code object testF at 0091FD60, file "temp.py", line 16>) 15 MAKE_FUNCTION 0 # data stack ��ɂ��� testF ���I�u�W�F�N�g�����ɂ��� dcrtF(.) �� CALL ���� 18 CALL_FUNCTION 1 21 STORE_NAME 1 (testF)
18 �o�C�g�ڂ� CALL_FUNCTION �� testF ���I�u�W�F�N�g�������ɂ��� dcrtF �����Ăяo���܂��B���̖߂�l���X�^�b�N�Ɏc����āA���� testF ���x���̈ʒu�� STORE_NAME ����܂��BtestF ���x���̒��g�� dcrtF(.) ���̖߂�l�F���I�u�W�F�N�g�Fclosure �ɒu���������܂��B
closure �Ƃ́A�l�X�g�������̓�������A�O���̊��̃��[�J���ϐ����Q�Ƃ��Ă���Ƃ��̓����̊��̂��Ƃ������܂��B
�������� def outerF(��ag1 ��, ag2, ...): �������� �������� ��at1 ��= 3 �������� print ag2 def innerF() �������� �������� inAt =��at1 ��+ ��ag1 �� �������� �������� print inAt �O���̊� outerF.func_code.co_cellvars:('ag1','at1') outerF.func_code.co_freevars:() �����̊� innerF.func_code.co_cellvars:() innerF.func_code.co_freevars:('ag1','at1')
��̗�̂悤�ɓ����̊� innerF(.) �́A�O���̊� outerF(.) �̃��[�J���ϐ��̂��� ag1, at1 �̓�̕ϐ����N���X���ĎQ�Ƃ��Ă��܂��B(�Ȃ� python �ł͈��������[�J���ϐ��ł� ag1 �����[�J���ϐ��ł��B)
�l�X�g�������ŃN���X���ĎQ�Ƃ���郍�[�J���ϐ��͓��ʈ�������˂Ȃ�܂���B���̎��s���� FrameObject.f_localsplus �̉��ɔz��Ƃ��Ĕz�u����܂��B���̂��߂� func_code.co_cellvars, func_code.co_freevars �ϐ��z����R���p�C�����ɒ�� CodeObject �ɑg�ݍ���ł����܂��Bco_cellvars �͊O���̊�����݂��N���X���ĎQ�Ƃ����ϐ��ł��Bco_freevars �͓����̊����猩���N���X���ĎQ�Ƃ����ϐ��ł��B���̂悤�� python code �Ŋm�F�ł��܂��B
//@@ def outerF(ag1, ag2): at1 = 3 print ag2 def innerF(): inAt = at1+ag1 print inAt print "co_cellvars:", innerF.func_code.co_cellvars print "co_freevars:", innerF.func_code.co_freevars print "co_cellvars:", outerF.func_code.co_cellvars print "co_freevars:", outerF.func_code.co_freevars print "----- call outerF() -------" outerF(1,2) //@@@ co_cellvars: ('ag1', 'at1') co_freevars: () ----- call outerF() ------- 2 co_cellvars: () co_freevars: ('ag1', 'at1')
���̂悤�� co_cellvars, co_freevars ���K�v�ɂȂ�̂́AinnerF ���I�u�W�F�N�g���Q�Ƃ��Ă���O���̃��[�J���ϐ��̒l�����I�u�W�F�N�g�̐������ɕۑ����Ă����˂Ȃ�Ȃ�����ł��B�Q�Ƃ����O���̃��[�J���ϐ��̒l�����I�u�W�F�N�g�ɕۑ����Ă����āAinnerF ���I�u�W�F�N�g�����s�����Ƃ��A�ۑ����Ă������O���̃��[�J���ϐ��̒l���g�����Ƃ� innerF �̓�����m���ɂ���K�v�����邽�߂ł��B
func_code.co_cellvars, func_code.co_freevars �ϐ��z��́A�N���X�ϐ��ϐ����O���̊�����݂�^�����̊�����݂邩�̈Ⴂ�ł��B�R���p�C�����ɒ�܂��Ă��܂��B���̃l�X�g����d�l�X�g�̂Ƃ���
outerF.func_code.co_cellvars == innerF.func_code.co_freevars
���̃l�X�g���O�d�l�X�g�ȏ�̂Ƃ���
outerF.func_code.co_cellvars �� innerF.func_code.co_freevars
closure �I�u�W�F�N�g�Ƃ� ['func_closure'] �v�f������ FunctionObject:���I�u�W�F�N�g�Ƃ������܂��B
ClosureObject �� FunctionObject + cell object
���� ���̂悤�ɁA�N���X���ĎQ�Ƃ���郍�[�J���ϐ��̗L���ɂ���� FunctionObject.func_closure �� None �ɂȂ����� cell �ɂȂ����肵�܂��B
# �l�X�g�������̊ԂŃ��[�J���ϐ��̃N���X�����Q�Ƃ����� //@@ def outerF(): inOutAt = 3 def innerF(): print inOutAt return innerF print outerF().func_closure //@@@ (<cell at 0x00923C50: int object at 0x008A56F0>,) # �l�X�Ƃ������̊ԂŃ��[�J���ϐ��̃N���X�����Q�Ƃ��Ȃ� //@@ def outerF(): inOutAt = 3 def innerF(): # print inOutAt print 5 return innerF print outerF().func_closure //@@@ None
���� cell �� func_code.co_freevars �z��ɑΉ������l�̃^�v���ł��BinnerF() ���̐錾���ɍ���܂��B�f�t�H���g�����l�̔z��Ɠ��l�� FunctionObject ���ێ����܂��B
FunctionObject.func_closure ���Ȃ킿 cell �^�v������邽�߂ɁA�N���[�W���[�����錾����Ă���ӏ��ł� MAKE_FUNCTION �̑���� MAKE_CLOSURE ���g���܂��B���̂悤�ȋ�ł��B
//@@ def outerF(): inOutAt = 3 def innerF(): print inOutAt return innerF import dis;dis.dis(outerF) //@@@ python temp.py 2 0 LOAD_CONST 1 (3) 3 STORE_DEREF 0 (inOutAt) 3 6 LOAD_CLOSURE 0 (inOutAt) 9 LOAD_CONST 2 (<code object innerF at 0091FC60, file "temp.py", line 3>) 12 MAKE_CLOSURE 0 15 STORE_FAST 0 (innerF) 6 18 LOAD_FAST 0 (innerF) 21 RETURN_VALUE
MAKE_CLOSURE �� ceval.c �\�[�X�͉��̂悤�ɂȂ��Ă��܂��B
case MAKE_CLOSURE: { int nfree; v = POP(); /* code object */ x = PyFunction_New(v, f->f_globals); #define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars)) nfree = PyCode_GetNumFree((PyCodeObject *)v); Py_DECREF(v); /* XXX Maybe this should be a separate opcode? */ if (x != NULL && nfree > 0) { # cell �̈���m�ۂ��܂� v = PyTuple_New(nfree); if (v == NULL) { Py_DECREF(x); x = NULL; break; } while (--nfree >= 0) { w = POP(); #define PyTuple_SET_ITEM(op, i, v) # (((PyTupleObject *)(op))->ob_item[i] = v) PyTuple_SET_ITEM(v, nfree, w); } # Cell �^�v���� FunctionObject �ɐݒ肵 ClosureObject �ɂ��܂� err = PyFunction_SetClosure(x, v); Py_DECREF(v); } if (x != NULL && oparg > 0) { # FunctionObject.func_defaults �^�v�����E�ݒ肵�܂� v = PyTuple_New(oparg); if (v == NULL) { Py_DECREF(x); x = NULL; break; } while (--oparg >= 0) { w = POP(); PyTuple_SET_ITEM(v, oparg, w); } err = PyFunction_SetDefaults(x, v); Py_DECREF(v); } PUSH(x); break; }MAKE_FUNCTION �Ɣ�r���Ă݂�uMAKE_CLOSURE == MAKE_FUNCTION + cell �̍쐬�v�ł��邱�Ƃ�����܂��B�������c�O�ł��� cell �̓��e�� inspect �Ō���܂���B
ClosureObject �� callable object �ł���ACALL_FUNCIION �ŏ�������܂��BFrameObject.f_localsplus �̃��[�J���ϐ��z��̎��ɁA�N���X���ĎQ�Ƃ���Ă���O���̃��[�J���ϐ��z���ݒ肵�܂��B�z��ʒu�� co_freevar[] �ϐ�������z��ƑΉ����܂��B
f_localsplus�������������������������� ��co_varnames[] �̏����Ʉ�fast_function(.)/do_call(.) �� �����ׂ�ꂽ local �ϐ� ��f_localsplus �̐����Ɛݒ���s���Ă��� �������������������������� ��co_freevars[] �̏����Ʉ� �����ׂ�ꂽ�O���� local�� ���ϐ� �� �������������������������� �� �� �� �� �� �� �� �� �������������������������� ��data stack �̈� �� ��������������������������
���� python code �Ŋ��̃l�X�g�� co_varnames/co_cellvars/co_freevars �̊W�����Ď���Ǝv���܂��B
//@@ # 07.07.18 test cell and free def outerF(): inOutAt = 3 def innerF(): inAt1 = 0 inAt2 = 0 innerAt = inOutAt + 3 inAt3 = 0 inAt4 = 0 def inInnerF(): inInnerAt = innerAt + 5 print inInnerAt return inInnerF import dis;dis.dis(innerF) return innerF outerF() //@@@ python temp.py 5 0 LOAD_CONST 1 (0) 3 STORE_FAST 5 (inAt1) 6 6 LOAD_CONST 1 (0) 9 STORE_FAST 4 (inAt2) 7 12 LOAD_DEREF 1 (inOutAt) 15 LOAD_CONST 2 (3) 18 BINARY_ADD 19 STORE_DEREF 0 (innerAt) 8 22 LOAD_CONST 1 (0) 25 STORE_FAST 3 (inAt3) 9 28 LOAD_CONST 1 (0) 31 STORE_FAST 2 (inAt4) 10 34 LOAD_CLOSURE 0 (innerAt) 37 LOAD_CONST 3 (<code object inInnerF at 0091FCA0, file "temp.py", line 10>) 40 MAKE_CLOSURE 0 43 STORE_FAST 1 (inInnerF) 13 46 LOAD_FAST 1 (inInnerF) 49 RETURN_VALUE //@@ # 07.07.18 test cell and free def outerF(): inOutAt = 3 def innerF(): inAt1 = 0 inAt2 = 0 innerAt = inOutAt + 3 inAt3 = 0 inAt4 = 0 def inInnerF(): inInnerAt = innerAt + 5 print inInnerAt print "inInnerF.func_code.co_cellvars:",inInnerF.func_code.co_cellvars print "inInnerF.func_code.co_freevars:",inInnerF.func_code.co_freevars return inInnerF #import dis;dis.dis(innerF) print "innerF.func_code.co_varnames:",innerF.func_code.co_varnames print "innerF.func_code.co_cellvars:",innerF.func_code.co_cellvars print "innerF.func_code.co_freevars:",innerF.func_code.co_freevars print return innerF print "outerF.func_code.co_varnames:",outerF.func_code.co_varnames print "outerF.func_code.co_cellvars:",outerF.func_code.co_cellvars print "outerF.func_code.co_freevars:",outerF.func_code.co_freevars print outerF() //@@@ python temp.py outerF.func_code.co_varnames: ('innerF', 'inOutAt') outerF.func_code.co_cellvars: ('inOutAt',) outerF.func_code.co_freevars: () innerF.func_code.co_varnames: ('innerAt', 'inInnerF', 'inAt4', 'inAt3', 'inAt2', 'inAt1') innerF.func_code.co_cellvars: ('innerAt',) innerF.func_code.co_freevars: ('inOutAt',)
��̃R�[�h�ł� innerF �� co_varname, co_cellvars, co_freevars ����ɒ��ׂĂ��܂��BinnerF() ���I�u�W�F�N�g�̃��[�J���ϐ��� ('innerAt', 'inInnerF', 'inAt4', 'inAt3', 'inAt2', 'inAt1') �ł��Bco_freevars �� ('inOutAt',) �ł��B���[�J���ϐ� co_varnames �� co_freevars �̊Ԃɂ͏d��������܂��BPython virtual machine code �� op-code �����Ă��d���������C���f�b�N�X�ԍ����^�����Ă��܂��BFrameObject.f_localsplus �ȉ��̃f�[�^�[�̈�͏d�������܂߂Ċm�ۂ���Ă���悤�ł��B
��� python �R�[�h�� parameter ��F�X�ƕς��ē������Ă݂�ƁApython �� closure �ł���Ă��邱�Ƃ��ǂ������Ă���Ǝv���܂��B
�N���X���� LOCAL �ϐ��̓ǂݏ����͉��� LOAD_DEREF/STORE_DEREF ���߂��g���܂��B���� C �\�[�X�E�R�[�h�́A��̃������z�u��O��ɂ���Ή���₷���ł��傤�B�܂�LOAD_FAST�^STORE_FAST���߂Ɨǂ����Ă��܂��B
case LOAD_DEREF: # oparg = NEXTARG(); i.e. 'i' of LOAD_CLOSURE i # freevars = f->f_localsplus + f->f_nlocals; x = freevars[oparg]; #define PyCell_GET(op) (((PyCellObject *)(op))->ob_ref) w = PyCell_Get(x); if (w != NULL) { PUSH(w); continue; } # �������牺�̓G���[���� err = -1; /* Don't stomp existing exception */ if (PyErr_Occurred()) break; if (oparg < f->f_ncells) { v = PyTuple_GetItem(co->co_cellvars, oparg); format_exc_check_arg( PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, v); } else { v = PyTuple_GetItem( co->co_freevars, oparg - f->f_ncells); format_exc_check_arg( PyExc_NameError, UNBOUNDFREE_ERROR_MSG, v); } break; �E �E case STORE_DEREF: # oparg = NEXTARG(); i.e. 'i' of LOAD_CLOSURE i # freevars = f->f_localsplus + f->f_nlocals; w = POP(); x = freevars[oparg]; #define PyCell_SET(op, v) (((PyCellObject *)(op))->ob_ref = v) PyCell_Set(x, w); Py_DECREF(w); continue;
���܂Ő������Ă������Ƃ�O��ɁApython �̃f�R���[�^�[�\���� disassembler �o�͂�����A���ꂪ��������Ă���̂������ł���͂��ł��B���́u���̎��s���Ԃ��v������f�R���[�^�[�\�����g���� python �v���O�����v�̓���� python virtual machine ���x���ŗ����ł���͂��ł��B
//@@ def dcrtF(fnAg): print "Now in dcrtF(.):",fnAg inFreeAt = 1 def innerF(objAg): print inFreeAt import time print "Now innerF(.)", objAg dbStartTimeAt = time.clock() fnAg(objAg) print time.clock() - dbStartTimeAt print "innerF.func_code.co_varnames:",innerF.func_code.co_varnames print "innerF.func_code.co_cellvars:",innerF.func_code.co_cellvars print "innerF.func_code.co_freevars:",innerF.func_code.co_freevars print "innerF.func_code.co_stacksize:",innerF.func_code.co_stacksize return innerF @dcrtF def testF():pass import dis;dis.dis(dcrtF) //@@@ Now in dcrtF(.): <function testF at 0x0091F4F0> innerF.func_code.co_varnames: ('objAg', 'dbStartTimeAt', 'time') innerF.func_code.co_cellvars: () innerF.func_code.co_freevars: ('inFreeAt', 'fnAg') innerF.func_code.co_stacksize: 2 2 0 LOAD_CONST 1 ('Now in dcrtF(.):') 3 PRINT_ITEM 4 LOAD_DEREF 0 (fnAg) 7 PRINT_ITEM 8 PRINT_NEWLINE 3 9 LOAD_CONST 2 (1) 12 STORE_DEREF 1 (inFreeAt) 5 15 LOAD_CLOSURE 1 (inFreeAt) 18 LOAD_CLOSURE 0 (fnAg) 21 LOAD_CONST 3 (<code object innerF at 0091FCA0, file "temp.py", line 5>) 24 MAKE_CLOSURE 0 27 STORE_FAST 2 (innerF) 14 30 LOAD_FAST 2 (innerF) 33 RETURN_VALUE
5 �s�ڂ� innerF(.) ���錾�� MAKE_CLOSURE �ɂ�� ClosureObject ������Ă��܂��B���� ClosureObject.func_closure �ɂ� (inFreeAt, fnAg) �̃^�v�����ݒ肳��Ă��܂��B���̂悤�� ClosureObject �� data stack �̃g�b�v�ɖ߂�l�Ƃ��Đς܂�� dcrtF(.) �̏������I����Ă��܂��B
���� ClosureObject ���f�R���[�^�[�� syntax sugar �̓����ɂ�� testF ���x���ɐݒ肳��܂��BtestF �� dcrtF �ɂ���� decorate ���ꂽ��́A���� testF(.) ���̎��s���Ԃ��v�����Ȃ��� testF(.) �����s���܂��B���� ClosureObject �Ō��� testF �����s�ł���̂� ClosureObject.func_closure ���Ȃ킿 cell �^�v���� testF ���I�u�W�F�N�g�ւ̎Q�ƒl���ݒ肳��Ă��邩��ł��BCallable Object �ł����� ClosureObject �ɑ� CALL_FUNCTION �����s����Ƃ��AFrameObject.f_localsplus �̃��[�J���ϐ��̔z��Ǝ��ɁAco_freevar �̏����� fnAg ���Ȃ킿���� testF �̎Q�ƒl�������Ă��邩��ł��B
���Ȃ킿�f�R���[�g�ς݂� testF �����s���悤�Ƃ����Ƃ��A���� FramObject.f_localspls �͉��̂悤�ɂȂ��Ă��邩��ł��B
FrameObject.f_localsplus������������������ ��objAg ��co_varnames: ('objAg', 'dbStartTimeAt', 'time') ������������������ ��dbStartTimeAt �� ������������������ ��time �� ������������������ ��inFreeAt ��co_freevars:('inFreeAt', 'fnAg') ������������������ ��fnAg==testF �� ������������������ data stack �̈愠 ��co_stacksize: 2 ������������������ �� �� ������������������
Python �� C �\�[�X�E�R�[�h��ǐՂ��邱�Ƃ͈ӊO�ƊȒP�ł��B���W���[���A���A�N���X���ׂĂ� FrameObject �� CodeObject �̑g�ݍ��킹�œ����Ă��邱�Ƃ𗝉����Ă����A PyFrameObject �\���̂𗝉������ ceval.c ��ǐՂł��܂��BPython virtual machine ���ǂ̂悤�ɓ����Ă���̂��ǐՂł��܂��B
���̂悤�ȒǐՂ��\�ɂȂ�� python ���ǂ̂悤�ɓ����Ă���̂� python virtual machine code ���x���ŗ����ł���悤�ɂȂ�܂��B����ɂ����f�R���[�^�[�\���ł��A�����ǂނ��A�����Ŋ���̎����R�[�h���e�X�g����ق��������葁�������ł���悤�ɂȂ�Ǝv���܂��B�@���ł��傤���B