Python 내부 메커니즘 - pyTypeObject 대상

PyTypeObject 대상
당신 은 나의 지난 글 에서 PyObject 중의 ob_type 구성원 에 대해 기억 하고 있 는 지 모 르 겠 습 니 다. 지난 글 에서 나 는 그것 을 전개 하지 않 았 습 니 다. 단지 독자 에 게 이것 이 현재 대상 이 어떤 유형 인지, 그리고 일부 유형 과 관련 된 정 보 를 가리 키 는 것 이 라 고 말 했 을 뿐 입 니 다. 그러면 본 박문 은 단독으로 ob_type 를 꺼 내 분석 하고 PyObject 대상 을 살 펴 보 았 습 니 다.당신 은 ob_type 구성원 이 struct _typeobject 인 것 을 발견 할 수 있 습 니 다. 이 데이터 구 조 는 Python 내부 에 또 다른 typedef 라 는 별명 이 있 습 니 다. 바로 PyTypeObject 이것 도 본 고 에서 분석 해 야 할 내부 대상 입 니 다. 이 데이터 구조 가 길 고 많은 데이터 구성원 이 있 기 때문에 코드 를 쉽게 읽 기 위해 저 는 모든 구성원 을 열거 하지 않 습 니 다.베일 을 조금씩 벗 기 는 거 야.
PyTypeObject 의 용 도 는?
Python 공식 문서 에서 PyTypeObject 는 Python 대상 체제 에서 가장 중요 한 구조 체 일 수도 있 습 니 다. 이 구조 체 는 새로운 유형 을 정의 할 수 있 기 때문에 이 구조 체 는 대상 의 행 위 를 통제 합 니 다. 또한 이 구조 체 는 Python 내부 의 다른 대상 에 비해 상당히 큽 니 다.이것 은 이 구조 체 가 대량의 데이터 구성원 과 대량의 C 함수 지침 을 저장 해 야 하기 때 문 입 니 다. 그 중에서 일부 유형 과 관련 된 편지 지침 이 포함 되 어 있 습 니 다. 전체적으로 말 하면 PyTypeObject 은 유형 대상 의 행 위 를 묘사 하 는 구조 체 입 니 다. 예 를 들 어 int 유형의 대상 과 string 유형의 대상 에 대해 이들 의 초기 화 는 분명 다 를 것 입 니 다.이들 의 인쇄 출력 방식, 이들 의 비교 연산 방식 은 모두 다 를 것 입 니 다. 따라서 모든 유형 대상 에 게 하나의 PyTypeObject 대상 이 이 유형 과 관련 된 데이터 구성원 과 함수 지침 을 저장 해 야 합 니 다. 또한 모든 유형 대상 은 초기 에 초기 화 PyTypeObject 대상 이 있어 야 합 니 다.유형 정 보 는 고정 되 었 습 니 다. 구체 적 인 세부 사항 은 부록 에서 새로운 유형 대상 을 어떻게 정의 하 는 지 참고 할 수 있 습 니 다. 위 에서 말 한 이론 을 잘 모 르 겠 습 니 다. 여러분 은 PyTypeObject 의 용 도 를 이해 하 셨 습 니까?다음은 Python 차원 에서 PyTypeObject 의 용 도 를 살 펴 보 겠 습 니 다.
>>> a = 1
>>> print a
>>> sa = "zhang"
>>> print sa

위 에서 int 대상 과 string 대상 을 간단하게 초기 화 했 습 니 다. 초기 화 할 때 malloc 는 얼마나 큰 공간 을 분배 해 야 합 니까?이 정 보 는 사실 PyTypeObject 에 저장 되 어 있 습 니 다. print 가 이 두 대상 을 인쇄 하 는 것 은 어떻게 인쇄 하 는 지 아 십 니까?C 언어 차원 에서 하나의 문자열 을 인쇄 하 는 것 과 하나의 정 수 를 인쇄 하 는 것 이 다 르 기 때문에 모든 유형 에 출력 을 어떻게 인쇄 해 야 하 는 지 PyTypeObject 에 저 장 됩 니 다. int 형식의 대상 에 게 크기 는 PyTypeObject 대상 의 tp_basicsize 데이터 구성원 에 두 고 int 대 PyTypeObject 초기 화 된 코드 를 통 해 볼 수 있 습 니 다.
typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* For printing, in format "." */                                                                                                  
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
    ......  //    N   
    printfunc tp_print; //          
    ......
}PyTypeObject;

./Include/object.h
int 대상 의 PyTypeObject 초기 화
PyTypeObject PyInt_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "int",
    sizeof(PyIntObject),
    ...... //    N       
    (printfunc)int_print,  //       
    ......
};

./Object/intobject.c
tpbasicsize 의 크기 는 sizeof (PyIntObject) 이 고 유형의 이름 은 int 입 니 다. 여기 보면 좀 알 겠 죠?int 형 대상 의 값 을 어떻게 인쇄 하 는 지 다시 한 번 봅 시다. PyTypeObject 에는 printfunction 형식의 함수 포인터 멤버 tp_print 가 있 습 니 다. 모든 유형 이 출력 되 려 면 이 함 수 를 실현 해 야 합 니 다. int 대상 이 실현 하 는 int_print 함 수 를 살 펴 보 겠 습 니 다.
static int
int_print(PyIntObject *v, FILE *fp, int flags)                                                                                                                            
     /* flags -- not used but required by interface */
{
    long int_val = v->ob_ival;
    Py_BEGIN_ALLOW_THREADS
    fprintf(fp, "%ld", int_val);
    Py_END_ALLOW_THREADS
    return 0;
}

. / Object / intobject. c 는 아직 알 아 볼 수 없 는 두 개의 매크로 Py_BEGIN_ALLOW_THREADS 를 무시 합 니 다. Py_END_ALLOW_THREADS 생각 은 간단 합 니 다. 바로 ob_ival 값 을 얻 은 다음 에 fprintf 를 통 해 인쇄 하 는 것 입 니 다. 이렇게 간단 합 니 다. 위의 두 가지 예 를 통 해 PyTypeObject 대상 의 중요성 과 용 도 를 알 게 될 것 이 라 고 믿 습 니 다.
PyTypeObject 구성
위 에서 PyTypeObject 대상 의 용도 에 대한 소 개 는 아직 구우일모 에 불과 합 니 다. 다음은 PyTypeObject 대상 이 어떤 부분 으로 구성 되 고 각 부분의 역할 이 어디 에 있 는 지 살 펴 보 겠 습 니 다.
typedef struct _typeobject {
    PyObject_VAR_HEAD
    char *tp_name; /* For printing, in format "." */
    int tp_basicsize, tp_itemsize; /* For allocation */
    .....
}; 

첫 번 째 부분 은 필수 적 인 유형 정보 이다. PyTypeObject 자체 도 하나의 대상 이기 때문에 PyObject_VAR_HEAD 이것 은 없어 서 는 안 될 것 이다. 그 다음은 유형의 명칭, 유형의 기본 크기, 유형 중의 요소 크기 이다. int 대상 에 대해 tp_itemsize 은 0 이다. int 대상 은 요소 의 개념 이 없 기 때문에 그 자체 가 하나의 전체 이 고 string 대상 tp_itemsize 은 0 이다.바로 1. string 대상 의 기본 요 소 는 char 입 니 다.
typedef struct _typeobject {
    ......
 /* Methods to implement standard operations */
    destructor tp_dealloc;
    printfunc tp_print;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    cmpfunc tp_compare;
    reprfunc tp_repr;
    .....
}; 

두 번 째 부분 은 표준 형식 과 관련 된 작업 입 니 다. 예 를 들 어 유형 대상 의 메모 리 를 어떻게 방출 하 는 지, 유형 대상 의 값 을 어떻게 인쇄 하 는 지, 두 가지 유형 대상 간 에 어떻게 비교 하 는 지, python 내장 함수 repr 를 호출 할 때 출력 하 는 것 은 무엇 입 니까?
typedef struct _typeobject {
    ......
   /* Method suites for standard classes */

    PyNumberMethods *tp_as_number;
    PySequenceMethods *tp_as_sequence;
    PyMappingMethods *tp_as_mapping;
    ......
};

세 번 째 부분 은 표준 대상 이 지원 하 는 조작 이다. 예 를 들 어 한 대상 이 수치 대상 으로 여 겨 지면 이 대상 은 어떤 조작 을 지원 해 야 하 는 지, 모든 조작의 구체 적 인 실현 이 어떤 것 인지, 만약 에 한 대상 이 하나의 서열 대상 으로 여 겨 진다 면 어떤 조작 을 지원 해 야 하 는 지, 만약 에 한 대상 이 관련 대상 으로 여 겨 진다 면그러면 어떤 조작 을 지원 해 야 하 는 지 여기 서 Python 의 또 다른 개념 을 이 끌 어 냈 습 니 다. 도 계 유형 측면 에서 분류 화 되 었 습 니 다. Python 에는 세 가지 대상 이 있 습 니 다. 하 나 는 수치 대상 이 고 하 나 는 서열 대상 이 며 마지막 하 나 는 관련 대상 입 니 다. 그 int 유형의 대상 에 대해 수치 대상 으로서 어떤 조작 이 필요 한 지 살 펴 보 겠 습 니 다.
static PyNumberMethods int_as_number = {
    (binaryfunc)int_add,        /*nb_add*/
    (binaryfunc)int_sub,        /*nb_subtract*/
    (binaryfunc)int_mul,        /*nb_multiply*/
    (binaryfunc)int_classic_div, /*nb_divide*/
    (binaryfunc)int_mod,        /*nb_remainder*/
    (binaryfunc)int_divmod,     /*nb_divmod*/
    (ternaryfunc)int_pow,       /*nb_power*/
    (unaryfunc)int_neg,         /*nb_negative*/
    (unaryfunc)int_int,         /*nb_positive*/
    (unaryfunc)int_abs,         /*nb_absolute*/
    (inquiry)int_nonzero,       /*nb_nonzero*/
    (unaryfunc)int_invert,      /*nb_invert*/
    (binaryfunc)int_lshift,     /*nb_lshift*/
    (binaryfunc)int_rshift,     /*nb_rshift*/
    (binaryfunc)int_and,        /*nb_and*/
    (binaryfunc)int_xor,        /*nb_xor*/
    (binaryfunc)int_or,         /*nb_or*/
    int_coerce,                 /*nb_coerce*/
    (unaryfunc)int_int,         /*nb_int*/
    (unaryfunc)int_long,        /*nb_long*/
    (unaryfunc)int_float,       /*nb_float*/
    (unaryfunc)int_oct,         /*nb_oct*/
    (unaryfunc)int_hex,         /*nb_hex*/
    0,                          /*nb_inplace_add*/
    0,                          /*nb_inplace_subtract*/
    0,                          /*nb_inplace_multiply*/
    0,                          /*nb_inplace_divide*/
    0,                          /*nb_inplace_remainder*/
    0,                          /*nb_inplace_power*/
    0,                          /*nb_inplace_lshift*/
    0,                          /*nb_inplace_rshift*/
    0,                          /*nb_inplace_and*/
    0,                          /*nb_inplace_xor*/
    0,                          /*nb_inplace_or*/
    (binaryfunc)int_div,        /* nb_floor_divide */
    (binaryfunc)int_true_divide, /* nb_true_divide */
    0,                          /* nb_inplace_floor_divide */
    0,                          /* nb_inplace_true_divide */
    (unaryfunc)int_int,         /* nb_index */
};

위 는 수치 대상 으로서 갖 춰 야 할 조작 들이다.
typedef struct _typeobject {
    .......
    /* Functions to access object as input/output buffer */
    PyBufferProcs *tp_as_buffer;

    /* Flags to define presence of optional/expanded features */
    long tp_flags;

    char *tp_doc; /* Documentation string */

    /* Assigned meaning in release 2.0 */
    /* call function for all accessible objects */
    traverseproc tp_traverse;

    /* delete references to contained objects */
    inquiry tp_clear;

    /* Assigned meaning in release 2.1 */
    /* rich comparisons */
    richcmpfunc tp_richcompare;

    /* weak reference enabler */
    long tp_weaklistoffset;

    /* Added in release 2.2 */
    /* Iterators */
    getiterfunc tp_iter;
    iternextfunc tp_iternext;
    ......
};

세 번 째 부분 은 교체 기, 약 한 인용, 문서 문자열 등 과 관련 된 일부 필드 로 편폭 에 국한 되 어 더 이상 소개 하지 않 습 니 다.
typedef struct _typeobject {
    ......
    /* Attribute descriptor and subclassing stuff */
    struct PyMethodDef *tp_methods;
    struct PyMemberDef *tp_members;
    struct PyGetSetDef *tp_getset;
    struct _typeobject *tp_base;
    PyObject *tp_dict;
    descrgetfunc tp_descr_get;
    descrsetfunc tp_descr_set;
    long tp_dictoffset;
    initproc tp_init;
    allocfunc tp_alloc;
    newfunc tp_new;
    freefunc tp_free; /* Low-level free-memory routine */
    inquiry tp_is_gc; /* For PyObject_IS_GC */
    PyObject *tp_bases;
    PyObject *tp_mro; /* method resolution order */
    PyObject *tp_cache;
    PyObject *tp_subclasses;
    PyObject *tp_weaklist;
    .......
};

네 번 째 부분 은 유형 대상 의 속성 정보 이 고 tp_methods 유형 대상 이 가지 고 있 는 구성원 방법 을 지정 했다. 예 를 들 어 string 대상 은 join, append 등 구성원 방법 이 있 고 tp_members 유형 이 가지 고 있 는 데이터 구성원 등 을 지적 했다. tp_getset 유형 대상 이 가지 고 있 는 get 류 와 set 류 의 조작 을 지적 했다. tp_base유형 대상 의 기본 클래스 를 가리 키 고 있 습 니 다. PyTypeObject 더 많은 관련 구성원 의 용도 와 해석 은 부록 의 문 서 를 참고 할 수 있 습 니 다.
Python 대상 의 다 태 성PyTypeObject 을 통 해 C 언어 차원 에서 이른바 다 태 성 을 실현 했다. 인쇄 를 통 해 아래 의 이 함 수 는 어떤 유형의 대상 과 도 정상적으로 인쇄 형식의 값 을 적용 할 수 있다.
void print(PyObject* object)
{
    object->ob_type->tp_print(object);
}

위의 함수 에 대해 string 형식 대상 이 들 어 오 면 string 형식 대상 PyTypeObject 대상 을 호출 합 니 다. 최종 호출 tp_print 은 string 형식 대상 이 스스로 실현 하 는 인쇄 함수 입 니 다. 마찬가지 로 int 형식 대상 이 들 어 오 면 최종 호출 tp_print 입 니 다.int 형식 대상 이 스스로 실현 하 는 인쇄 함수 입 니 다. 이것 이 바로 python 에서 다 중 구현 입 니 다.
부록
새로운 타 입 Type Object 를 사용자 정의 하 는 방법

좋은 웹페이지 즐겨찾기