�ڎ�

2008y 08m 12d

dis/inspect ���W���[���� ceval.c ���g���� Python �̃n�b�L���O

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 interpreter

dis ���W���[��

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 �̓K�p

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

kbplay.py: hex byte code �\���‚��̋t�A�b�Z���u��

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



�֐��ɑ����� func_code �I�u�W�F�N�g��co_varnames, co_names, co_consts ����

�֐��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 interpreter

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

�ėp CPU �̓���

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

Python Virtual Machine �� FrameObject

���ʂ� 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

ceval.c:Python Virtual Machine �� C �\�[�X�E�R�[�h

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

PyFrameObject �\����

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

ceval.c �\�[�X

PyFrameObject �\���̂𗝉������ ceval.c �\�[�X��ǂ���悤�ɂ��Ȃ�܂��B

PyObject * PyEval_EvalFrame(PyFrameObject *f) �֐�

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

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���[��

inspect ���W���[���� python ������Ԃ𒲂׏グ�Đl�Ԃɉ���₷���`�ŕ񍐂�����@�\��Z�߂����W���[���ł��B�������ȉ��ł� python code �𒲂ׂ邽�߂̋@�\�Ɍ��肵�Đ������܂��BFrameObject �o�R�Œ��ׂ���@�\�𒆐S�ɐ������Ă����܂�

CodeObject/FramObject/FunctionObject

���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_, func_, co_ ���O�t���K��

f_locals, func_globals, co_varnames �ȂǂɎ����@�\�̕ϐ������A���ꂩ�牽�x���o�Ă��܂��B�����̕ϐ����Őړ����� f_, func_, co_ �͉��̈Ӗ��������Ă��܂��B

������ f_ �� functiontion �̈Ӗ��Ɍ�����₷���̂ł����Aframe �̈Ӗ��ł��B������o���Ă����ƁAinspect �Ȃ� python �̒��g��`�����ނƂ��y�ɂȂ�܂��B

FrameObject Stack

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(FrameObject)

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

inspect.getmembers(FrameObject.f_code)

������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

inspect �o�R�ɂ�� ���W���[���� disassemble

�֐��ł͂Ȃ����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)

inspect ���g��Ȃ� ���W���[���� disassemble

���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 ���N���X�ɓK�p����

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 ���g������s�R�[�h

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]) )

python �R�[�h�� hack

���܂Ő������Ă��� 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

x,y = y,x, x,z,y = z,y,x

�܂��͎�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

Python �I�u�W�F�N�g

�������ݍ���Ł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                    ��
    ��                            ��
    ��������������������������������

Python �I�u�W�F�N�g�̐����Ɩ����̊Ǘ�

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��

�܂��֐��Ăя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

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�� func_defaults �z��ɐݒ肷��

�֐��̃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

CALL_FUNCTION

���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)

���[�J���E�O���[�o���ϐ���STORE/LOAD_FAST, STORE/LOAG_GLOBAL

python �ɂ�����ϐ��̃X�R�[�v�̋K���� LEGB ���[���Ő�������܂��B���̐����̔w��ɂ���l�������Adisassembler �̏o�͂Ɗ֐��� func_code ��������f�����Ƃ��ł��܂��B

�ϐ��̃X�R�[�v:LEGB ���[��

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

���[�J���ϐ��ƃO���[�o���ϐ��̈Ⴂ

���� 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        
__builtins__ �ϐ�

�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.py

  2           0 LOAD_GLOBAL              0 (zip) # ������ "zip" �ւ̎Q��
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE        
�r���g�C���ϐ��̃X�R�[�v

�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

function.func_globals
MAKE_FUNCTION ���s���������� FunctionObject �͏o���オ���Ă��܂��BFunctionObject.fun_globals ���o���オ���Ă��܂��BCALL_FUNCTION �͊֐��̌Ăяo�����Ƃ� FrameObject �����܂��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__', ),
 ('__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')]
���̂悤�� FunctionObject.func_globals ���������o���܂�
//@@
#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': }
function.func_defaults

�֐������Ƀ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
function.func_dict

���̂悤�Ɂ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}
STORE_FAST/LOAD_FAST

���܂Ő������Ă������[�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

STORE_GLOBAL/LOAD_GLOBAL

���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

STORE_GLOBAL/STORE_NAME

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

inspect �o�R�ɂ�� �N���X�� disassemble

�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

LOAD_ATTRI

���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')



���X�g

�����ł� 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




hash

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

hash �Ƃ�

IT �p�ꎫ�T�ł́u�n�b�V���@�v�͎��̂悤�ɐ�������Ă��܂��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

hashable == imutable �ł͂Ȃ�

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 �֐��̎��

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



generator

�����ł� python �� generator �� python virtual machine �̃��x���Œ��ׂČ��܂��傤�Bgenerator �֐��̂킩��ɂ����_�͉��̓�‚ł��B

�ȉ��A��̓�‚̗l�q�����ڍׂɒ��ׂĂ݂܂��傤�B

generatorObject �̐���

�����ł� python interpreter �� generatorObject �𐶐�����ڍׂȗl�q��`������ł݂܂��傤�B

for loop

���� 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

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        

generator �֐��ƕ��ʂ̊֐��́A�֐��I�u�W�F�N�g�ɂ����� �Ⴂ

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

ceval.c �ɂ����� CO_GENERATOR �t���O�̈���

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



yield ���� context switch

generator �֐��� yield ���͊֐��̎��s�𒆒f���܂��BgeneratorObject.next() ���\�b�h�́A���f���ꂽ�������ĊJ���܂��B

���v���N�����́A�֐���r���Œ��f��������ĊJ�������肷�邱�Ƃ� python �ł͗e�Ղł���Ƃ�����͂��ł��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

generator �� co-operative thread

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

thread

�����ł� python �� thread �Œ��ӂ��ׂ��_�Ƒ΍�ɂ‚��� python virtual machine �̃��x���ōl���܂��BPython �ł� thread �������@�ɂ‚��Ē��ׂ����ƁApython thread �̖��_�ɂ‚��Č������܂��B

python �ɂ����� thread �̎���

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

thread programm �L�q�̖��_

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

thread �Ԃ̋��ʕϐ��̖��

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

thread �Ԃ̋��ʕϐ��� test and set ���

���ʕϐ��������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

random ���W���[�����Ɏg���� thread �ԋ��ʕϐ����̌���

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 �\���̃n�b�N

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

�u�������F syntax sugar

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

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

ClosureObject �� FunctionObject + cell object

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

MAKE_CLOSURE

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

LOAD_DEREF �� co_cellvars[h, co_freevars

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;

decorator

���܂Ő������Ă������Ƃ�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