Python 내부 메커니즘 - pyTypeObject 대상
15054 단어 Python 기초 및 진급
당신 은 나의 지난 글 에서
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 를 사용자 정의 하 는 방법