SlideShare ist ein Scribd-Unternehmen logo
1 von 108
Downloaden Sie, um offline zu lesen
“Внутренности” CPython, часть вторая
Никита Лесников
Вспомнить все.
“Внутренности” CPython, часть вторая 2
Вспомнить все
Наверняка не все присутствовали на первой части моего
выступления
“Внутренности” CPython, часть вторая 3
Вспомнить все
Наверняка не все присутствовали на первой части моего
выступления
Это ведь было аж в июне
“Внутренности” CPython, часть вторая 3
Вспомнить все
Наверняка не все присутствовали на первой части моего
выступления
Это ведь было аж в июне
Поэтому кратко повторю, о чем мы собираемся разговаривать
“Внутренности” CPython, часть вторая 3
CPython
Основная реализация на сегодняшний день
“Внутренности” CPython, часть вторая 4
CPython
Основная реализация на сегодняшний день
Написана на C
“Внутренности” CPython, часть вторая 4
CPython
Основная реализация на сегодняшний день
Написана на C
“Чистый” интерпретатор байткода, без JIT и AOT
“Внутренности” CPython, часть вторая 4
CPython
Основная реализация на сегодняшний день
Написана на C
“Чистый” интерпретатор байткода, без JIT и AOT
“Своя” VM, никаких отсылок к Java и .NET
“Внутренности” CPython, часть вторая 4
Альтернативы
native+ - PyPy
“Внутренности” CPython, часть вторая 5
Альтернативы
native+ - PyPy
.NET - IronPython, Boo (правда, строго говоря это не Python)
“Внутренности” CPython, часть вторая 5
Альтернативы
native+ - PyPy
.NET - IronPython, Boo (правда, строго говоря это не Python)
JVM - Jython
“Внутренности” CPython, часть вторая 5
Альтернативы
native+ - PyPy
.NET - IronPython, Boo (правда, строго говоря это не Python)
JVM - Jython
Возможно другие. Они нас сегодня не интересуют.
“Внутренности” CPython, часть вторая 5
Альтернативы
native+ - PyPy
.NET - IronPython, Boo (правда, строго говоря это не Python)
JVM - Jython
Возможно другие. Они нас сегодня не интересуют.
Мы рассматриваем внутреннее устройство CPython.
“Внутренности” CPython, часть вторая 5
Все - объект
В CPython все является объектом
“Внутренности” CPython, часть вторая 6
Все - объект
В CPython все является объектом
Конкретнее - PyObject*
“Внутренности” CPython, часть вторая 6
Все - объект
В CPython все является объектом
Конкретнее - PyObject*
Числа, строки, код, фреймы, модули - абсолютно все
“Внутренности” CPython, часть вторая 6
Все - объект
В CPython все является объектом
Конкретнее - PyObject*
Числа, строки, код, фреймы, модули - абсолютно все
Любой PyObject начинается одинаково:
#define PyObject_HEAD 
Py_ssize_t ob_refcnt; 
struct _typeobject *ob_type;
“Внутренности” CPython, часть вторая 6
PyObject
#define PyObject_HEAD 
Py_ssize_t ob_refcnt; 
struct _typeobject *ob_type;
ob_refcnt - reference count для управления памятью
“Внутренности” CPython, часть вторая 7
PyObject
#define PyObject_HEAD 
Py_ssize_t ob_refcnt; 
struct _typeobject *ob_type;
ob_refcnt - reference count для управления памятью
ob_type - type object, задающий поведение конкретного объекта
“Внутренности” CPython, часть вторая 7
PyObject
#define PyObject_HEAD 
Py_ssize_t ob_refcnt; 
struct _typeobject *ob_type;
ob_refcnt - reference count для управления памятью
ob_type - type object, задающий поведение конкретного объекта
То, что дальше, может быть чем угодно.
“Внутренности” CPython, часть вторая 7
code object
Код в Python - тоже объект.
“Внутренности” CPython, часть вторая 8
code object
Код в Python - тоже объект.
Интерпретатор оперирует байткодом стековой машины.
“Внутренности” CPython, часть вторая 8
code object
Код в Python - тоже объект.
Интерпретатор оперирует байткодом стековой машины.
Инструкции занимают 1 байт, опционально принимают один
двухбайтный аргумент.
“Внутренности” CPython, часть вторая 8
code object
Код в Python - тоже объект.
Интерпретатор оперирует байткодом стековой машины.
Инструкции занимают 1 байт, опционально принимают один
двухбайтный аргумент.
Константы сложных типов хранятся “рядом” в code object,
обращение к ним происходит по индексу.
“Внутренности” CPython, часть вторая 8
code object
def f(x): return (1,2,3)[x] + 1
0 LOAD_CONST 4 ((1, 2, 3))
3 LOAD_FAST 0 (x)
6 BINARY_SUBSCR
7 LOAD_CONST 1 (1)
10 BINARY_ADD
11 RETURN_VALUE
>>> f.__code__.co_consts
(None, 1, 2, 3, (1, 2, 3))
“Внутренности” CPython, часть вторая 9
Стеки и фреймы.
“Внутренности” CPython, часть вторая 10
Стековая машина
На уровне байткода CPython является стековой машиной.
“Внутренности” CPython, часть вторая 11
Стековая машина
На уровне байткода CPython является стековой машиной.
Значения кладутся на стек, операции берут их с вершины стека,
иногда меняя порядок верхних элементов.
“Внутренности” CPython, часть вторая 11
Стековая машина
На уровне байткода CPython является стековой машиной.
Значения кладутся на стек, операции берут их с вершины стека,
иногда меняя порядок верхних элементов.
Стек значений не имеет отношения к стеку адресов возврата - это
отдельная сущность.
“Внутренности” CPython, часть вторая 11
Стековая машина, пример
def f(a,b,c): return a + b*c
0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 LOAD_FAST 2 (c)
9 BINARY_MULTIPLY
10 BINARY_ADD
11 RETURN_VALUE
“Внутренности” CPython, часть вторая 12
Нелокальный выход
Стек значений (value stack) существует в рамках одного
исполнения code object
“Внутренности” CPython, часть вторая 13
Нелокальный выход
Стек значений (value stack) существует в рамках одного
исполнения code object
Python поддерживает нелокальный выход (break, continue,
raise)
“Внутренности” CPython, часть вторая 13
Нелокальный выход
Стек значений (value stack) существует в рамках одного
исполнения code object
Python поддерживает нелокальный выход (break, continue,
raise)
Необходимо “открутить” стек значений на момент входа в for,
while или локальный try
“Внутренности” CPython, часть вторая 13
Нелокальный выход
Стек значений (value stack) существует в рамках одного
исполнения code object
Python поддерживает нелокальный выход (break, continue,
raise)
Необходимо “открутить” стек значений на момент входа в for,
while или локальный try
С++ использует для stack unwind при исключениях пометки в
“общем” стеке
“Внутренности” CPython, часть вторая 13
Нелокальный выход
Стек значений (value stack) существует в рамках одного
исполнения code object
Python поддерживает нелокальный выход (break, continue,
raise)
Необходимо “открутить” стек значений на момент входа в for,
while или локальный try
С++ использует для stack unwind при исключениях пометки в
“общем” стеке
CPython использует для этих целей block stack.
“Внутренности” CPython, часть вторая 13
Block stack
Block stack хранит в себе пары вида (адрес, глубина стека)
“Внутренности” CPython, часть вторая 14
Block stack
Block stack хранит в себе пары вида (адрес, глубина стека)
Инструкции вроде break “откручивают” value stack до
запомненного значения глубины и делают goto на указанный
адрес в байткоде
“Внутренности” CPython, часть вторая 14
Block stack
Block stack хранит в себе пары вида (адрес, глубина стека)
Инструкции вроде break “откручивают” value stack до
запомненного значения глубины и делают goto на указанный
адрес в байткоде
Давайте посмотрим как это выглядит
“Внутренности” CPython, часть вторая 14
Block stack, пример
def f():
while 1:
return 2; continue; break
0 SETUP_LOOP 8 (to 11)
>> 3 LOAD_CONST 1 (2)
6 RETURN_VALUE
7 BREAK_LOOP
8 JUMP_ABSOLUTE 3
>> 11 LOAD_CONST 0 (None)
14 RETURN_VALUE
“Внутренности” CPython, часть вторая 15
ceval.c
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg,
STACK_LEVEL());
continue;
“Внутренности” CPython, часть вторая 16
ceval.c, BREAK
case BREAK_LOOP:
why = WHY_BREAK;
goto fast_block_end;
fast_block_end:
while (why != WHY_NOT && f->f_iblock > 0) {
PyTryBlock *b = PyFrame_BlockPop(f);
if (b->b_type == SETUP_LOOP && why == WHY_BREAK) {
why = WHY_NOT;
JUMPTO(b->b_handler);
break; }
“Внутренности” CPython, часть вторая 17
Другие хранилища
Помимо value stack и block stack, нужно еще хранить адреса
возврата, локальные переменные, лексическое замыкание
“Внутренности” CPython, часть вторая 18
Другие хранилища
Помимо value stack и block stack, нужно еще хранить адреса
возврата, локальные переменные, лексическое замыкание
В прошлой части этой презентации рассказывалось, что
локальные переменные определяются на этапе компиляции и для
них заводится список фиксированного размера с обращением по
индексу за O(1)
“Внутренности” CPython, часть вторая 18
Другие хранилища
Помимо value stack и block stack, нужно еще хранить адреса
возврата, локальные переменные, лексическое замыкание
В прошлой части этой презентации рассказывалось, что
локальные переменные определяются на этапе компиляции и для
них заводится список фиксированного размера с обращением по
индексу за O(1)
Аналогично компилятор (в байткод) поступает и с лексическим
замыканием
“Внутренности” CPython, часть вторая 18
Другие хранилища
Помимо value stack и block stack, нужно еще хранить адреса
возврата, локальные переменные, лексическое замыкание
В прошлой части этой презентации рассказывалось, что
локальные переменные определяются на этапе компиляции и для
них заводится список фиксированного размера с обращением по
индексу за O(1)
Аналогично компилятор (в байткод) поступает и с лексическим
замыканием
Кроме того, code object может вызвать сам себя (рекурсия?) и
тогда обоим экземплярам нужны свои стеки.
“Внутренности” CPython, часть вторая 18
frame object
Является хранилищем состояния для конкретного code object
“Внутренности” CPython, часть вторая 19
frame object
Является хранилищем состояния для конкретного code object
Без code object не имеет смысла - все его параметры
определяются атрибутами исполняемого кода
“Внутренности” CPython, часть вторая 19
frame object
Является хранилищем состояния для конкретного code object
Без code object не имеет смысла - все его параметры
определяются атрибутами исполняемого кода
Включает в себя value stack, block stack, locals, cellvars
“Внутренности” CPython, часть вторая 19
frame object
Является хранилищем состояния для конкретного code object
Без code object не имеет смысла - все его параметры
определяются атрибутами исполняемого кода
Включает в себя value stack, block stack, locals, cellvars
Ссылается на предыдущий фрейм в стеке
“Внутренности” CPython, часть вторая 19
frame object
frame object - полный аналог activation frame в С
“Внутренности” CPython, часть вторая 20
frame object
frame object - полный аналог activation frame в С
Только в C activation frame расположен на общем стеке - адреса
возврата и локальные переменные идут “вперемешку”, и activation
frame волей-неволей уничтожается при выходе из функции
(последующие вызовы других функций его перетрут).
“Внутренности” CPython, часть вторая 20
frame object
frame object - полный аналог activation frame в С
Только в C activation frame расположен на общем стеке - адреса
возврата и локальные переменные идут “вперемешку”, и activation
frame волей-неволей уничтожается при выходе из функции
(последующие вызовы других функций его перетрут).
В frame object есть ссылка f_back на предыдущий фрейм в стеке,
поэтому в CPython стек вызовов реализован как односвязный
список.
“Внутренности” CPython, часть вторая 20
Почему односвязный список?
В отличие от contiguous представления стека в C, это позволяет
продлевать время жизни фрейма сколь угодно долго.
“Внутренности” CPython, часть вторая 21
Почему односвязный список?
В отличие от contiguous представления стека в C, это позволяет
продлевать время жизни фрейма сколь угодно долго.
Каждый фрейм выделяется и освобождается как обычный
PyObject, в подходящем месте в памяти, совершенно
необязательно кого-то перетирать.
“Внутренности” CPython, часть вторая 21
Почему односвязный список?
В отличие от contiguous представления стека в C, это позволяет
продлевать время жизни фрейма сколь угодно долго.
Каждый фрейм выделяется и освобождается как обычный
PyObject, в подходящем месте в памяти, совершенно
необязательно кого-то перетирать.
Это позволяет реализовать генераторы.
“Внутренности” CPython, часть вторая 21
Генераторы
Это просто стек (в виде списка) фреймов, завернутый в объект
(genobject).
“Внутренности” CPython, часть вторая 22
Генераторы
Это просто стек (в виде списка) фреймов, завернутый в объект
(genobject).
yield приостанавливает его выполнение, next() возобновляет c
того места, где в последний раз был вызван yield
“Внутренности” CPython, часть вторая 22
Генераторы
Это просто стек (в виде списка) фреймов, завернутый в объект
(genobject).
yield приостанавливает его выполнение, next() возобновляет c
того места, где в последний раз был вызван yield
Стек фреймов живет столько, сколько живет genobject.
“Внутренности” CPython, часть вторая 22
Генераторы и фреймы
code 1
code 2
code gencode 3
code 4
genobject
f_code
f_back
f_code
locals
f_back
f_code
f_back
f_code
f_back
f_code
f_back
f_code
f_back
f_code
f_back
f_code
f_back
“Внутренности” CPython, часть вторая 23
Генераторы
Генераторы в CPython не столь общи, как хотелось бы
“Внутренности” CPython, часть вторая 24
Генераторы
Генераторы в CPython не столь общи, как хотелось бы
Во-первых, yield это statement, а не expression
“Внутренности” CPython, часть вторая 24
Генераторы
Генераторы в CPython не столь общи, как хотелось бы
Во-первых, yield это statement, а не expression
Во-вторых, yield возможен только в самой функции-генераторе,
нo не в вызываемых ею
“Внутренности” CPython, часть вторая 24
Генераторы
Генераторы в CPython не столь общи, как хотелось бы
Во-первых, yield это statement, а не expression
Во-вторых, yield возможен только в самой функции-генераторе,
нo не в вызываемых ею
Оба ограничения нефундаментальны
“Внутренности” CPython, часть вторая 24
Генераторы - альтернативы
PEP 380 - официально принятый для Python 3 пропоузал,
который позволит реализовывать полноценные сопрограммы на
генераторах (как, например, в Lua)
“Внутренности” CPython, часть вторая 25
Генераторы - альтернативы
PEP 380 - официально принятый для Python 3 пропоузал,
который позволит реализовывать полноценные сопрограммы на
генераторах (как, например, в Lua)
greenlet - нативный модуль расширения для CPython,
реализующий кооперативную многозадачность через “срезание”
сишного стека
“Внутренности” CPython, часть вторая 25
Генераторы - альтернативы
PEP 380 - официально принятый для Python 3 пропоузал,
который позволит реализовывать полноценные сопрограммы на
генераторах (как, например, в Lua)
greenlet - нативный модуль расширения для CPython,
реализующий кооперативную многозадачность через “срезание”
сишного стека
stackless - форк CPython, развивающий идею “фреймы как
объекты” до полноценной кооперативной многозадачности
“Внутренности” CPython, часть вторая 25
Объектная модель
“Внутренности” CPython, часть вторая 26
Объектная модель
Ранее мы уже упоминали, что все с точки зрения CPython есть
PyObject
“Внутренности” CPython, часть вторая 27
Объектная модель
Ранее мы уже упоминали, что все с точки зрения CPython есть
PyObject
Также мы знаем, что в байткоде инструкция BINARY_ADD удаляет
два объекта с вершины стека, складывает их, после чего
помещает результат на вершину стека
“Внутренности” CPython, часть вторая 27
Объектная модель
Ранее мы уже упоминали, что все с точки зрения CPython есть
PyObject
Также мы знаем, что в байткоде инструкция BINARY_ADD удаляет
два объекта с вершины стека, складывает их, после чего
помещает результат на вершину стека
Сложение для чисел - это сложение, для строк - конкатенация, и
вообще мы можем переопределить __add__ у чего угодно
“Внутренности” CPython, часть вторая 27
Объектная модель
Ранее мы уже упоминали, что все с точки зрения CPython есть
PyObject
Также мы знаем, что в байткоде инструкция BINARY_ADD удаляет
два объекта с вершины стека, складывает их, после чего
помещает результат на вершину стека
Сложение для чисел - это сложение, для строк - конкатенация, и
вообще мы можем переопределить __add__ у чего угодно
Как интерпретатор узнает, что делать?
“Внутренности” CPython, часть вторая 27
Type object, слоты, протоколы
В самом начале мы упомянули, что у PyObject обязательно
присутствует поле ob_type - ссылка на type object
“Внутренности” CPython, часть вторая 28
Type object, слоты, протоколы
В самом начале мы упомянули, что у PyObject обязательно
присутствует поле ob_type - ссылка на type object
Оказывается, в type object есть слоты, возвращающие реализации
требуемых операций (если те поддерживаются объектом, само
собой)
“Внутренности” CPython, часть вторая 28
Type object, слоты, протоколы
В самом начале мы упомянули, что у PyObject обязательно
присутствует поле ob_type - ссылка на type object
Оказывается, в type object есть слоты, возвращающие реализации
требуемых операций (если те поддерживаются объектом, само
собой)
Интерпретатор просто вызывает нужные функции по указателям,
либо возвращает ошибку несовместимости типов.
“Внутренности” CPython, часть вторая 28
Type object, слоты, протоколы
В самом начале мы упомянули, что у PyObject обязательно
присутствует поле ob_type - ссылка на type object
Оказывается, в type object есть слоты, возвращающие реализации
требуемых операций (если те поддерживаются объектом, само
собой)
Интерпретатор просто вызывает нужные функции по указателям,
либо возвращает ошибку несовместимости типов.
Рассмотрим на примере int object.
“Внутренности” CPython, часть вторая 28
ceval.c
case BINARY_ADD:
w = POP();
v = TOP();
....
else {
slow_add:
x = PyNumber_Add(v, w);
}
...
SET_TOP(x);
“Внутренности” CPython, часть вторая 29
abstract.c
PyObject * PyNumber_Add(PyObject *v, PyObject *w)
{
PyObject *result = binary_op1(v, w, NB_SLOT(nb_add));
...
return result;
}
“Внутренности” CPython, часть вторая 30
abstract.c
static PyObject
*binary_op1(PyObject *v, PyObject *w, const int op_slot)
{
binaryfunc slotv = NULL;
...
slotv = NB_BINOP(v->ob_type->tp_as_number, op_slot);
...
if (slotv) {
x = slotv(v, w);
if (x != Py_NotImplemented)
return x;
“Внутренности” CPython, часть вторая 31
intobject.c
static PyObject *
int_add(PyIntObject *v, PyIntObject *w)
{
register long a, b, x;
CONVERT_TO_LONG(v, a);
CONVERT_TO_LONG(w, b);
....
x = (long)((unsigned long)a + b);
if ((x^a) >= 0 || (x^b) >= 0)
return PyInt_FromLong(x);
....
“Внутренности” CPython, часть вторая 32
Слоты и протоколы
Слоты и протоколы - это довольно низкоуровневая особенность,
которая из кода на Python не видна
“Внутренности” CPython, часть вторая 33
Слоты и протоколы
Слоты и протоколы - это довольно низкоуровневая особенность,
которая из кода на Python не видна
Как она сочетается с наследованием и возможностью
переопределения через “магические” имена (вроде __add__?)
“Внутренности” CPython, часть вторая 33
Слоты и протоколы
Слоты и протоколы - это довольно низкоуровневая особенность,
которая из кода на Python не видна
Как она сочетается с наследованием и возможностью
переопределения через “магические” имена (вроде __add__?)
В этом проявляется красота объектной модели Python.
“Внутренности” CPython, часть вторая 33
type object == class
type object и классы - одно и то же.
“Внутренности” CPython, часть вторая 34
type object == class
type object и классы - одно и то же.
(За исключением old style classes, которые все являются
объектами типа instance и фактически существуют только ради
совместимости с legacy кодом на Python < 2.5)
“Внутренности” CPython, часть вторая 34
type object == class
type object и классы - одно и то же.
(За исключением old style classes, которые все являются
объектами типа instance и фактически существуют только ради
совместимости с legacy кодом на Python < 2.5)
При создании класса создается новый type object, который
наполняется содержимым из классов-родителей.
“Внутренности” CPython, часть вторая 34
type object == class
При наследовании классов все слоты type object копируются в
новый класс (typeobject.c):
static PyObject *
type_new(PyTypeObject *metatype,
PyObject *args, PyObject *kwds)
{
...
/* Put the proper slots in place */
fixup_slot_dispatchers(type);
“Внутренности” CPython, часть вторая 35
type object == class
При попытке переопределить метод в рантайме через выставление
“магического” атрибута класса в дело включается type_setattro,
определенный в слоте tp_setattro у типа класса
“Внутренности” CPython, часть вторая 36
type object == class
При попытке переопределить метод в рантайме через выставление
“магического” атрибута класса в дело включается type_setattro,
определенный в слоте tp_setattro у типа класса
Да, у type object тоже есть тип, и это тоже type object :)
“Внутренности” CPython, часть вторая 36
type object == class
При попытке переопределить метод в рантайме через выставление
“магического” атрибута класса в дело включается type_setattro,
определенный в слоте tp_setattro у типа класса
Да, у type object тоже есть тип, и это тоже type object :)
type_setattro знает про слоты и правильно их обновляет:
static int
type_setattro(PyTypeObject *type,
PyObject *name, PyObject *value)
{
...
return update_slot(type, name);
“Внутренности” CPython, часть вторая 36
type object == class
Кроме того, технические поля инстанса (вроде __dict__), также
являются с точки зрения типа обычными аттрибутами
“Внутренности” CPython, часть вторая 37
type object == class
Кроме того, технические поля инстанса (вроде __dict__), также
являются с точки зрения типа обычными аттрибутами
Вкупе с дескрипторами, про которые много кто уже здесь
говорил, это дает поистине впечатляющие возможности
“Внутренности” CPython, часть вторая 37
type object == class
Кроме того, технические поля инстанса (вроде __dict__), также
являются с точки зрения типа обычными аттрибутами
Вкупе с дескрипторами, про которые много кто уже здесь
говорил, это дает поистине впечатляющие возможности
В частности, практически ко всему, во что можно впихнуть
заголовок PyObject, можно предоставить идиоматичную
питоновскую обертку, не меняя представления
“Внутренности” CPython, часть вторая 37
type object == class
Кроме того, технические поля инстанса (вроде __dict__), также
являются с точки зрения типа обычными аттрибутами
Вкупе с дескрипторами, про которые много кто уже здесь
говорил, это дает поистине впечатляющие возможности
В частности, практически ко всему, во что можно впихнуть
заголовок PyObject, можно предоставить идиоматичную
питоновскую обертку, не меняя представления
Это обуславливает такое количество библиотек - делать
интерфейсы для C/C++ библиотек довольно легко
“Внутренности” CPython, часть вторая 37
slots
Чтобы поменять представление объекта в памяти, необязательно
лезть на уровень Python/C API
“Внутренности” CPython, часть вторая 38
slots
Чтобы поменять представление объекта в памяти, необязательно
лезть на уровень Python/C API
Для объектов, которые создаются миллионами и редко меняют
набор полей, есть встроенная возможность избежать создания
__dict__ для каждого инстанса.
“Внутренности” CPython, часть вторая 38
slots
Чтобы поменять представление объекта в памяти, необязательно
лезть на уровень Python/C API
Для объектов, которые создаются миллионами и редко меняют
набор полей, есть встроенная возможность избежать создания
__dict__ для каждого инстанса.
Для этого в классе надо объявить атрибут __slots__, и в нем
объявить имена полей.
“Внутренности” CPython, часть вторая 38
slots
Чтобы поменять представление объекта в памяти, необязательно
лезть на уровень Python/C API
Для объектов, которые создаются миллионами и редко меняют
набор полей, есть встроенная возможность избежать создания
__dict__ для каждого инстанса.
Для этого в классе надо объявить атрибут __slots__, и в нем
объявить имена полей.
Тогда все инстансы будут хранить только ссылки на значения
атрибутов в определенном порядке, __dict__ будет создан только
при попытке выставить атрибут не из __slots__.
“Внутренности” CPython, часть вторая 38
slots
>>> class SlotClass: __slots__ = "x", "y"
>>> X = SlotClass()
>>> X.x = 1; X.y = 2
>>> asizeof(X)
128
>>> class DictClass: pass
>>> Y = DictClass()
>>> Y.x = 1; Y.y = 2
>>> asizeof(Y)
480
“Внутренности” CPython, часть вторая 39
Заключение
“Внутренности” CPython, часть вторая 40
Заключение
Напоследок хочу напомнить, что все рассказанное может быть
почерпнуто прямо из исходников CPython - они хорошо
задокументированы и читаются довольно легко
“Внутренности” CPython, часть вторая 41
Заключение
Напоследок хочу напомнить, что все рассказанное может быть
почерпнуто прямо из исходников CPython - они хорошо
задокументированы и читаются довольно легко
Лезть в исходники интерпретатора чтобы понять, как ведет себя
прикладной код - вполне себе реальный сценарий
“Внутренности” CPython, часть вторая 41
Заключение
Напоследок хочу напомнить, что все рассказанное может быть
почерпнуто прямо из исходников CPython - они хорошо
задокументированы и читаются довольно легко
Лезть в исходники интерпретатора чтобы понять, как ведет себя
прикладной код - вполне себе реальный сценарий
Если тема доклада вас заинтересовала, то от себя хочу
порекомендовать следующие ресурсы
“Внутренности” CPython, часть вторая 41
“Python Innards”, Yaniv Aknin
http://en.wordpress.com/tag/pythons-innards/
Серия постов от Yaniv Aknin про байткод, стеки,
thread state и объектную модель в CPython.
“Внутренности” CPython, часть вторая 42
“Python internals”, Eli Bendersky
http://tinyurl.com/pyinternals
Серия постов от Eli Bendersky про компилятор
Python, а также объектную модель Python 3.
“Внутренности” CPython, часть вторая 43
“Understanding the Python GIL”, David Beazley
http://www.dabeaz.com/GIL/
Презентации David Beazley, касающиеся
особенностей реализации GIL в Python,
проливающие свет на его неочевидное поведение
(например, существенное замедление CPU-bound
многопоточного кода на многоядерных машинах)
“Внутренности” CPython, часть вторая 44
Благодарю за внимание!
Вопросы?

Weitere ähnliche Inhalte

Was ist angesagt?

Fabric для управления серверами
Fabric для управления серверамиFabric для управления серверами
Fabric для управления серверамиMaxim Kulsha
 
SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек
SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотекSWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек
SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотекPython Meetup
 
Flask как хорошее решение для веб проекта
Flask как хорошее решение для веб проектаFlask как хорошее решение для веб проекта
Flask как хорошее решение для веб проектаPython Meetup
 
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Stas Vyschepan
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Yandex
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияPlatonov Sergey
 
Мой Python всегда со мной!
Мой Python всегда со мной!Мой Python всегда со мной!
Мой Python всегда со мной!PyNSK
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Sergey Platonov
 
[Defcon Russia #29] Михаил Клементьев - Обнаружение руткитов в GNU/Linux
[Defcon Russia #29] Михаил Клементьев - Обнаружение руткитов в GNU/Linux[Defcon Russia #29] Михаил Клементьев - Обнаружение руткитов в GNU/Linux
[Defcon Russia #29] Михаил Клементьев - Обнаружение руткитов в GNU/LinuxDefconRussia
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython Meetup
 
Сладкое будущее: Phalcon и Zephir
Сладкое будущее: Phalcon и ZephirСладкое будущее: Phalcon и Zephir
Сладкое будущее: Phalcon и ZephirCodeFest
 
Почему Rust стоит вашего внимания
Почему Rust стоит вашего вниманияПочему Rust стоит вашего внимания
Почему Rust стоит вашего вниманияMichael Pankov
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptSergey Platonov
 
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)Ontico
 
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)Ontico
 
Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальBadoo Development
 

Was ist angesagt? (20)

Fabric для управления серверами
Fabric для управления серверамиFabric для управления серверами
Fabric для управления серверами
 
SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек
SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотекSWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек
SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек
 
Flask как хорошее решение для веб проекта
Flask как хорошее решение для веб проектаFlask как хорошее решение для веб проекта
Flask как хорошее решение для веб проекта
 
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server ...
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
 
Python и Cython
Python и CythonPython и Cython
Python и Cython
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
 
Kotlin with API tests
Kotlin with API testsKotlin with API tests
Kotlin with API tests
 
Мой Python всегда со мной!
Мой Python всегда со мной!Мой Python всегда со мной!
Мой Python всегда со мной!
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
 
[Defcon Russia #29] Михаил Клементьев - Обнаружение руткитов в GNU/Linux
[Defcon Russia #29] Михаил Клементьев - Обнаружение руткитов в GNU/Linux[Defcon Russia #29] Михаил Клементьев - Обнаружение руткитов в GNU/Linux
[Defcon Russia #29] Михаил Клементьев - Обнаружение руткитов в GNU/Linux
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.by
 
Сладкое будущее: Phalcon и Zephir
Сладкое будущее: Phalcon и ZephirСладкое будущее: Phalcon и Zephir
Сладкое будущее: Phalcon и Zephir
 
Почему Rust стоит вашего внимания
Почему Rust стоит вашего вниманияПочему Rust стоит вашего внимания
Почему Rust стоит вашего внимания
 
Tomita одесса
Tomita одессаTomita одесса
Tomita одесса
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
 
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
Сравнение форматов и библиотек сериализации / Антон Рыжов (Qrator Labs)
 
Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон Довгаль
 

Andere mochten auch

Dictionary в Python. По мотивам Objects/dictnotes.txt
Dictionary в Python. По мотивам Objects/dictnotes.txtDictionary в Python. По мотивам Objects/dictnotes.txt
Dictionary в Python. По мотивам Objects/dictnotes.txtPython Meetup
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPython Meetup
 
ekbpy'2012- Юрий Юревич - Как сделать REST API на Python
ekbpy'2012- Юрий Юревич - Как сделать REST API на Pythonekbpy'2012- Юрий Юревич - Как сделать REST API на Python
ekbpy'2012- Юрий Юревич - Как сделать REST API на Pythonit-people
 
Неочевидное поведение некоторых конструкций
Неочевидное поведение некоторых конструкцийНеочевидное поведение некоторых конструкций
Неочевидное поведение некоторых конструкцийPython Meetup
 
Разработка сетевых приложений с gevent
Разработка сетевых приложений с geventРазработка сетевых приложений с gevent
Разработка сетевых приложений с geventAndrey Popp
 
Беглый обзор "внутренностей" Python
Беглый обзор "внутренностей" PythonБеглый обзор "внутренностей" Python
Беглый обзор "внутренностей" PythonPython Meetup
 
Метод всех пар, или как не убиться тестируя комбинации
Метод всех пар, или как не убиться тестируя комбинацииМетод всех пар, или как не убиться тестируя комбинации
Метод всех пар, или как не убиться тестируя комбинацииSQALab
 
собеседование тестировщиков что спросить и как ответить
собеседование тестировщиков   что спросить и как ответитьсобеседование тестировщиков   что спросить и как ответить
собеседование тестировщиков что спросить и как ответитьAlex Baranouski
 
Мобильный платформы AMD 2013
Мобильный платформы AMD 2013Мобильный платформы AMD 2013
Мобильный платформы AMD 2013Lysenko Andrey
 
особенности научных презентаций
особенности научных презентацийособенности научных презентаций
особенности научных презентацийAnastasia Starostina
 
Очередной скучный доклад про логгирование
Очередной скучный доклад про логгированиеОчередной скучный доклад про логгирование
Очередной скучный доклад про логгированиеPython Meetup
 
Этологичная презентация
Этологичная презентацияЭтологичная презентация
Этологичная презентацияMihail Neustroev
 
Fastvisuals - первый презентационный коучинг 1000 идей на 10 слайдах
Fastvisuals - первый презентационный коучинг 1000 идей на 10 слайдахFastvisuals - первый презентационный коучинг 1000 идей на 10 слайдах
Fastvisuals - первый презентационный коучинг 1000 идей на 10 слайдахFastvisuals
 
Domain-тестирование
Domain-тестированиеDomain-тестирование
Domain-тестированиеSPB SQA Group
 
Почему презентации так трудно делать?
Почему презентации так трудно делать?Почему презентации так трудно делать?
Почему презентации так трудно делать?Alexei Kapterev
 
How I got 2.5 Million views on Slideshare (by @nickdemey - Board of Innovation)
How I got 2.5 Million views on Slideshare (by @nickdemey - Board of Innovation)How I got 2.5 Million views on Slideshare (by @nickdemey - Board of Innovation)
How I got 2.5 Million views on Slideshare (by @nickdemey - Board of Innovation)Board of Innovation
 
The Seven Deadly Social Media Sins
The Seven Deadly Social Media SinsThe Seven Deadly Social Media Sins
The Seven Deadly Social Media SinsXPLAIN
 
Five Killer Ways to Design The Same Slide
Five Killer Ways to Design The Same SlideFive Killer Ways to Design The Same Slide
Five Killer Ways to Design The Same SlideCrispy Presentations
 
How People Really Hold and Touch (their Phones)
How People Really Hold and Touch (their Phones)How People Really Hold and Touch (their Phones)
How People Really Hold and Touch (their Phones)Steven Hoober
 

Andere mochten auch (20)

Dictionary в Python. По мотивам Objects/dictnotes.txt
Dictionary в Python. По мотивам Objects/dictnotes.txtDictionary в Python. По мотивам Objects/dictnotes.txt
Dictionary в Python. По мотивам Objects/dictnotes.txt
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
 
ekbpy'2012- Юрий Юревич - Как сделать REST API на Python
ekbpy'2012- Юрий Юревич - Как сделать REST API на Pythonekbpy'2012- Юрий Юревич - Как сделать REST API на Python
ekbpy'2012- Юрий Юревич - Как сделать REST API на Python
 
Неочевидное поведение некоторых конструкций
Неочевидное поведение некоторых конструкцийНеочевидное поведение некоторых конструкций
Неочевидное поведение некоторых конструкций
 
Разработка сетевых приложений с gevent
Разработка сетевых приложений с geventРазработка сетевых приложений с gevent
Разработка сетевых приложений с gevent
 
Беглый обзор "внутренностей" Python
Беглый обзор "внутренностей" PythonБеглый обзор "внутренностей" Python
Беглый обзор "внутренностей" Python
 
Метод всех пар, или как не убиться тестируя комбинации
Метод всех пар, или как не убиться тестируя комбинацииМетод всех пар, или как не убиться тестируя комбинации
Метод всех пар, или как не убиться тестируя комбинации
 
собеседование тестировщиков что спросить и как ответить
собеседование тестировщиков   что спросить и как ответитьсобеседование тестировщиков   что спросить и как ответить
собеседование тестировщиков что спросить и как ответить
 
Мобильный платформы AMD 2013
Мобильный платформы AMD 2013Мобильный платформы AMD 2013
Мобильный платформы AMD 2013
 
особенности научных презентаций
особенности научных презентацийособенности научных презентаций
особенности научных презентаций
 
Очередной скучный доклад про логгирование
Очередной скучный доклад про логгированиеОчередной скучный доклад про логгирование
Очередной скучный доклад про логгирование
 
Этологичная презентация
Этологичная презентацияЭтологичная презентация
Этологичная презентация
 
Fastvisuals - первый презентационный коучинг 1000 идей на 10 слайдах
Fastvisuals - первый презентационный коучинг 1000 идей на 10 слайдахFastvisuals - первый презентационный коучинг 1000 идей на 10 слайдах
Fastvisuals - первый презентационный коучинг 1000 идей на 10 слайдах
 
Domain-тестирование
Domain-тестированиеDomain-тестирование
Domain-тестирование
 
Почему презентации так трудно делать?
Почему презентации так трудно делать?Почему презентации так трудно делать?
Почему презентации так трудно делать?
 
The Minimum Loveable Product
The Minimum Loveable ProductThe Minimum Loveable Product
The Minimum Loveable Product
 
How I got 2.5 Million views on Slideshare (by @nickdemey - Board of Innovation)
How I got 2.5 Million views on Slideshare (by @nickdemey - Board of Innovation)How I got 2.5 Million views on Slideshare (by @nickdemey - Board of Innovation)
How I got 2.5 Million views on Slideshare (by @nickdemey - Board of Innovation)
 
The Seven Deadly Social Media Sins
The Seven Deadly Social Media SinsThe Seven Deadly Social Media Sins
The Seven Deadly Social Media Sins
 
Five Killer Ways to Design The Same Slide
Five Killer Ways to Design The Same SlideFive Killer Ways to Design The Same Slide
Five Killer Ways to Design The Same Slide
 
How People Really Hold and Touch (their Phones)
How People Really Hold and Touch (their Phones)How People Really Hold and Touch (their Phones)
How People Really Hold and Touch (their Phones)
 

Ähnlich wie "Внутренности" CPython, часть II

Spring the Ripper by Evgeny Borisov
Spring the Ripper by Evgeny BorisovSpring the Ripper by Evgeny Borisov
Spring the Ripper by Evgeny BorisovJavaDayUA
 
ekbpy'2012 - Марк Коренберг - Системное программирование на Питоне
ekbpy'2012 - Марк Коренберг - Системное программирование на Питонеekbpy'2012 - Марк Коренберг - Системное программирование на Питоне
ekbpy'2012 - Марк Коренберг - Системное программирование на Питонеit-people
 
Поговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийПоговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийAndrey Akinshin
 
Иван Кочуркин. Теория и практика парсинга формальных языков
Иван Кочуркин. Теория и практика парсинга формальных языковИван Кочуркин. Теория и практика парсинга формальных языков
Иван Кочуркин. Теория и практика парсинга формальных языковMskDotNet Community
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...Sigma Software
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Platonov Sergey
 
Как это работает: DLR
Как это работает: DLRКак это работает: DLR
Как это работает: DLRMikhail Shcherbakov
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программированияguestfc8ae0
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНСit-people
 
Python и высокая нагрузка
Python и высокая нагрузкаPython и высокая нагрузка
Python и высокая нагрузкаAlexander Shigin
 
Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомTatyanazaxarova
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Dima Dzuba
 
Консольные приложения на Go
Консольные приложения на GoКонсольные приложения на Go
Консольные приложения на GoAndrey Smirnov
 
ekbpy'2012 - Михаил Коробов - Python 3
ekbpy'2012 - Михаил Коробов - Python 3ekbpy'2012 - Михаил Коробов - Python 3
ekbpy'2012 - Михаил Коробов - Python 3it-people
 

Ähnlich wie "Внутренности" CPython, часть II (20)

Spring the Ripper by Evgeny Borisov
Spring the Ripper by Evgeny BorisovSpring the Ripper by Evgeny Borisov
Spring the Ripper by Evgeny Borisov
 
Spring the ripper
Spring the ripperSpring the ripper
Spring the ripper
 
ekbpy'2012 - Марк Коренберг - Системное программирование на Питоне
ekbpy'2012 - Марк Коренберг - Системное программирование на Питонеekbpy'2012 - Марк Коренберг - Системное программирование на Питоне
ekbpy'2012 - Марк Коренберг - Системное программирование на Питоне
 
Поговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийПоговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложений
 
Иван Кочуркин. Теория и практика парсинга формальных языков
Иван Кочуркин. Теория и практика парсинга формальных языковИван Кочуркин. Теория и практика парсинга формальных языков
Иван Кочуркин. Теория и практика парсинга формальных языков
 
Spring puzzlers
Spring puzzlersSpring puzzlers
Spring puzzlers
 
C++ теория
C++ теорияC++ теория
C++ теория
 
C++ теория
C++ теорияC++ теория
C++ теория
 
C++ теория
C++ теорияC++ теория
C++ теория
 
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
Опыт применения активных объектов во встраиваемых системах. Архитектурные асп...
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Как это работает: DLR
Как это работает: DLRКак это работает: DLR
Как это работает: DLR
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программирования
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
 
Python и высокая нагрузка
Python и высокая нагрузкаPython и высокая нагрузка
Python и высокая нагрузка
 
Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментом
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
 
Консольные приложения на Go
Консольные приложения на GoКонсольные приложения на Go
Консольные приложения на Go
 
Python infrastructure from scratch
Python infrastructure from scratchPython infrastructure from scratch
Python infrastructure from scratch
 
ekbpy'2012 - Михаил Коробов - Python 3
ekbpy'2012 - Михаил Коробов - Python 3ekbpy'2012 - Михаил Коробов - Python 3
ekbpy'2012 - Михаил Коробов - Python 3
 

Mehr von Python Meetup

Machine learning with Python / Олег Шидловский / Doist [Python Meetup 27.03.15]
Machine learning with Python / Олег Шидловский / Doist [Python Meetup 27.03.15] Machine learning with Python / Олег Шидловский / Doist [Python Meetup 27.03.15]
Machine learning with Python / Олег Шидловский / Doist [Python Meetup 27.03.15] Python Meetup
 
Как скачать статистику игроков World of Tanks / Павел Пересторонин [Python Me...
Как скачать статистику игроков World of Tanks / Павел Пересторонин [Python Me...Как скачать статистику игроков World of Tanks / Павел Пересторонин [Python Me...
Как скачать статистику игроков World of Tanks / Павел Пересторонин [Python Me...Python Meetup
 
Почему я пишу хороший код, но его никто не ценит, кроме моей мамы / Павел Меш...
Почему я пишу хороший код, но его никто не ценит, кроме моей мамы / Павел Меш...Почему я пишу хороший код, но его никто не ценит, кроме моей мамы / Павел Меш...
Почему я пишу хороший код, но его никто не ценит, кроме моей мамы / Павел Меш...Python Meetup
 
OpenSource CMS и ERP система в одном флаконе / Олег Курьян / технический дире...
OpenSource CMS и ERP система в одном флаконе / Олег Курьян / технический дире...OpenSource CMS и ERP система в одном флаконе / Олег Курьян / технический дире...
OpenSource CMS и ERP система в одном флаконе / Олег Курьян / технический дире...Python Meetup
 
Про асинхронность / Максим Щепелин / Web Developer Wargaming
Про асинхронность / Максим Щепелин / Web Developer WargamingПро асинхронность / Максим Щепелин / Web Developer Wargaming
Про асинхронность / Максим Щепелин / Web Developer WargamingPython Meetup
 
S.O.L.I.D. - Павел Кохан, Python Meetup 26.09.2014
S.O.L.I.D. - Павел Кохан, Python Meetup 26.09.2014S.O.L.I.D. - Павел Кохан, Python Meetup 26.09.2014
S.O.L.I.D. - Павел Кохан, Python Meetup 26.09.2014Python Meetup
 
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Python Meetup
 
Wargaming: тыл - фронту!
Wargaming: тыл - фронту!Wargaming: тыл - фронту!
Wargaming: тыл - фронту!Python Meetup
 
Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Python Meetup
 
Redis. Как мы боролись со сложностью
Redis. Как мы боролись со сложностьюRedis. Как мы боролись со сложностью
Redis. Как мы боролись со сложностьюPython Meetup
 
Обзор фреймворка Twisted
Обзор фреймворка TwistedОбзор фреймворка Twisted
Обзор фреймворка TwistedPython Meetup
 
Обзор способов написания конкурентных программ в питоне
Обзор способов написания конкурентных программ в питоне Обзор способов написания конкурентных программ в питоне
Обзор способов написания конкурентных программ в питоне Python Meetup
 
Python для анализа данных
Python для анализа данныхPython для анализа данных
Python для анализа данныхPython Meetup
 
Асинхронное распределенное выполнение задач. Stdlib, Celery, RQ и собственные...
Асинхронное распределенное выполнение задач. Stdlib, Celery, RQ и собственные...Асинхронное распределенное выполнение задач. Stdlib, Celery, RQ и собственные...
Асинхронное распределенное выполнение задач. Stdlib, Celery, RQ и собственные...Python Meetup
 
Использование gevent для эмуляции высокой нагрузки
Использование gevent для эмуляции высокой нагрузкиИспользование gevent для эмуляции высокой нагрузки
Использование gevent для эмуляции высокой нагрузкиPython Meetup
 
Введение в GIL и новый GIL
Введение в GIL и новый GILВведение в GIL и новый GIL
Введение в GIL и новый GILPython Meetup
 
Недостатки Python
Недостатки PythonНедостатки Python
Недостатки PythonPython Meetup
 
Социальный игровой сервер на Python: от первого коммита до продакшена
Социальный игровой сервер на Python: от первого коммита до продакшенаСоциальный игровой сервер на Python: от первого коммита до продакшена
Социальный игровой сервер на Python: от первого коммита до продакшенаPython Meetup
 
Портируем на Python 3
Портируем на Python 3Портируем на Python 3
Портируем на Python 3Python Meetup
 

Mehr von Python Meetup (20)

Machine learning with Python / Олег Шидловский / Doist [Python Meetup 27.03.15]
Machine learning with Python / Олег Шидловский / Doist [Python Meetup 27.03.15] Machine learning with Python / Олег Шидловский / Doist [Python Meetup 27.03.15]
Machine learning with Python / Олег Шидловский / Doist [Python Meetup 27.03.15]
 
Как скачать статистику игроков World of Tanks / Павел Пересторонин [Python Me...
Как скачать статистику игроков World of Tanks / Павел Пересторонин [Python Me...Как скачать статистику игроков World of Tanks / Павел Пересторонин [Python Me...
Как скачать статистику игроков World of Tanks / Павел Пересторонин [Python Me...
 
Почему я пишу хороший код, но его никто не ценит, кроме моей мамы / Павел Меш...
Почему я пишу хороший код, но его никто не ценит, кроме моей мамы / Павел Меш...Почему я пишу хороший код, но его никто не ценит, кроме моей мамы / Павел Меш...
Почему я пишу хороший код, но его никто не ценит, кроме моей мамы / Павел Меш...
 
OpenSource CMS и ERP система в одном флаконе / Олег Курьян / технический дире...
OpenSource CMS и ERP система в одном флаконе / Олег Курьян / технический дире...OpenSource CMS и ERP система в одном флаконе / Олег Курьян / технический дире...
OpenSource CMS и ERP система в одном флаконе / Олег Курьян / технический дире...
 
Про асинхронность / Максим Щепелин / Web Developer Wargaming
Про асинхронность / Максим Щепелин / Web Developer WargamingПро асинхронность / Максим Щепелин / Web Developer Wargaming
Про асинхронность / Максим Щепелин / Web Developer Wargaming
 
S.O.L.I.D. - Павел Кохан, Python Meetup 26.09.2014
S.O.L.I.D. - Павел Кохан, Python Meetup 26.09.2014S.O.L.I.D. - Павел Кохан, Python Meetup 26.09.2014
S.O.L.I.D. - Павел Кохан, Python Meetup 26.09.2014
 
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
 
Wargaming: тыл - фронту!
Wargaming: тыл - фронту!Wargaming: тыл - фронту!
Wargaming: тыл - фронту!
 
Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"
 
Redis. Как мы боролись со сложностью
Redis. Как мы боролись со сложностьюRedis. Как мы боролись со сложностью
Redis. Как мы боролись со сложностью
 
Обзор фреймворка Twisted
Обзор фреймворка TwistedОбзор фреймворка Twisted
Обзор фреймворка Twisted
 
Обзор способов написания конкурентных программ в питоне
Обзор способов написания конкурентных программ в питоне Обзор способов написания конкурентных программ в питоне
Обзор способов написания конкурентных программ в питоне
 
Pebble
PebblePebble
Pebble
 
Python для анализа данных
Python для анализа данныхPython для анализа данных
Python для анализа данных
 
Асинхронное распределенное выполнение задач. Stdlib, Celery, RQ и собственные...
Асинхронное распределенное выполнение задач. Stdlib, Celery, RQ и собственные...Асинхронное распределенное выполнение задач. Stdlib, Celery, RQ и собственные...
Асинхронное распределенное выполнение задач. Stdlib, Celery, RQ и собственные...
 
Использование gevent для эмуляции высокой нагрузки
Использование gevent для эмуляции высокой нагрузкиИспользование gevent для эмуляции высокой нагрузки
Использование gevent для эмуляции высокой нагрузки
 
Введение в GIL и новый GIL
Введение в GIL и новый GILВведение в GIL и новый GIL
Введение в GIL и новый GIL
 
Недостатки Python
Недостатки PythonНедостатки Python
Недостатки Python
 
Социальный игровой сервер на Python: от первого коммита до продакшена
Социальный игровой сервер на Python: от первого коммита до продакшенаСоциальный игровой сервер на Python: от первого коммита до продакшена
Социальный игровой сервер на Python: от первого коммита до продакшена
 
Портируем на Python 3
Портируем на Python 3Портируем на Python 3
Портируем на Python 3
 

"Внутренности" CPython, часть II

  • 1. “Внутренности” CPython, часть вторая Никита Лесников
  • 3. Вспомнить все Наверняка не все присутствовали на первой части моего выступления “Внутренности” CPython, часть вторая 3
  • 4. Вспомнить все Наверняка не все присутствовали на первой части моего выступления Это ведь было аж в июне “Внутренности” CPython, часть вторая 3
  • 5. Вспомнить все Наверняка не все присутствовали на первой части моего выступления Это ведь было аж в июне Поэтому кратко повторю, о чем мы собираемся разговаривать “Внутренности” CPython, часть вторая 3
  • 6. CPython Основная реализация на сегодняшний день “Внутренности” CPython, часть вторая 4
  • 7. CPython Основная реализация на сегодняшний день Написана на C “Внутренности” CPython, часть вторая 4
  • 8. CPython Основная реализация на сегодняшний день Написана на C “Чистый” интерпретатор байткода, без JIT и AOT “Внутренности” CPython, часть вторая 4
  • 9. CPython Основная реализация на сегодняшний день Написана на C “Чистый” интерпретатор байткода, без JIT и AOT “Своя” VM, никаких отсылок к Java и .NET “Внутренности” CPython, часть вторая 4
  • 11. Альтернативы native+ - PyPy .NET - IronPython, Boo (правда, строго говоря это не Python) “Внутренности” CPython, часть вторая 5
  • 12. Альтернативы native+ - PyPy .NET - IronPython, Boo (правда, строго говоря это не Python) JVM - Jython “Внутренности” CPython, часть вторая 5
  • 13. Альтернативы native+ - PyPy .NET - IronPython, Boo (правда, строго говоря это не Python) JVM - Jython Возможно другие. Они нас сегодня не интересуют. “Внутренности” CPython, часть вторая 5
  • 14. Альтернативы native+ - PyPy .NET - IronPython, Boo (правда, строго говоря это не Python) JVM - Jython Возможно другие. Они нас сегодня не интересуют. Мы рассматриваем внутреннее устройство CPython. “Внутренности” CPython, часть вторая 5
  • 15. Все - объект В CPython все является объектом “Внутренности” CPython, часть вторая 6
  • 16. Все - объект В CPython все является объектом Конкретнее - PyObject* “Внутренности” CPython, часть вторая 6
  • 17. Все - объект В CPython все является объектом Конкретнее - PyObject* Числа, строки, код, фреймы, модули - абсолютно все “Внутренности” CPython, часть вторая 6
  • 18. Все - объект В CPython все является объектом Конкретнее - PyObject* Числа, строки, код, фреймы, модули - абсолютно все Любой PyObject начинается одинаково: #define PyObject_HEAD Py_ssize_t ob_refcnt; struct _typeobject *ob_type; “Внутренности” CPython, часть вторая 6
  • 19. PyObject #define PyObject_HEAD Py_ssize_t ob_refcnt; struct _typeobject *ob_type; ob_refcnt - reference count для управления памятью “Внутренности” CPython, часть вторая 7
  • 20. PyObject #define PyObject_HEAD Py_ssize_t ob_refcnt; struct _typeobject *ob_type; ob_refcnt - reference count для управления памятью ob_type - type object, задающий поведение конкретного объекта “Внутренности” CPython, часть вторая 7
  • 21. PyObject #define PyObject_HEAD Py_ssize_t ob_refcnt; struct _typeobject *ob_type; ob_refcnt - reference count для управления памятью ob_type - type object, задающий поведение конкретного объекта То, что дальше, может быть чем угодно. “Внутренности” CPython, часть вторая 7
  • 22. code object Код в Python - тоже объект. “Внутренности” CPython, часть вторая 8
  • 23. code object Код в Python - тоже объект. Интерпретатор оперирует байткодом стековой машины. “Внутренности” CPython, часть вторая 8
  • 24. code object Код в Python - тоже объект. Интерпретатор оперирует байткодом стековой машины. Инструкции занимают 1 байт, опционально принимают один двухбайтный аргумент. “Внутренности” CPython, часть вторая 8
  • 25. code object Код в Python - тоже объект. Интерпретатор оперирует байткодом стековой машины. Инструкции занимают 1 байт, опционально принимают один двухбайтный аргумент. Константы сложных типов хранятся “рядом” в code object, обращение к ним происходит по индексу. “Внутренности” CPython, часть вторая 8
  • 26. code object def f(x): return (1,2,3)[x] + 1 0 LOAD_CONST 4 ((1, 2, 3)) 3 LOAD_FAST 0 (x) 6 BINARY_SUBSCR 7 LOAD_CONST 1 (1) 10 BINARY_ADD 11 RETURN_VALUE >>> f.__code__.co_consts (None, 1, 2, 3, (1, 2, 3)) “Внутренности” CPython, часть вторая 9
  • 27. Стеки и фреймы. “Внутренности” CPython, часть вторая 10
  • 28. Стековая машина На уровне байткода CPython является стековой машиной. “Внутренности” CPython, часть вторая 11
  • 29. Стековая машина На уровне байткода CPython является стековой машиной. Значения кладутся на стек, операции берут их с вершины стека, иногда меняя порядок верхних элементов. “Внутренности” CPython, часть вторая 11
  • 30. Стековая машина На уровне байткода CPython является стековой машиной. Значения кладутся на стек, операции берут их с вершины стека, иногда меняя порядок верхних элементов. Стек значений не имеет отношения к стеку адресов возврата - это отдельная сущность. “Внутренности” CPython, часть вторая 11
  • 31. Стековая машина, пример def f(a,b,c): return a + b*c 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b) 6 LOAD_FAST 2 (c) 9 BINARY_MULTIPLY 10 BINARY_ADD 11 RETURN_VALUE “Внутренности” CPython, часть вторая 12
  • 32. Нелокальный выход Стек значений (value stack) существует в рамках одного исполнения code object “Внутренности” CPython, часть вторая 13
  • 33. Нелокальный выход Стек значений (value stack) существует в рамках одного исполнения code object Python поддерживает нелокальный выход (break, continue, raise) “Внутренности” CPython, часть вторая 13
  • 34. Нелокальный выход Стек значений (value stack) существует в рамках одного исполнения code object Python поддерживает нелокальный выход (break, continue, raise) Необходимо “открутить” стек значений на момент входа в for, while или локальный try “Внутренности” CPython, часть вторая 13
  • 35. Нелокальный выход Стек значений (value stack) существует в рамках одного исполнения code object Python поддерживает нелокальный выход (break, continue, raise) Необходимо “открутить” стек значений на момент входа в for, while или локальный try С++ использует для stack unwind при исключениях пометки в “общем” стеке “Внутренности” CPython, часть вторая 13
  • 36. Нелокальный выход Стек значений (value stack) существует в рамках одного исполнения code object Python поддерживает нелокальный выход (break, continue, raise) Необходимо “открутить” стек значений на момент входа в for, while или локальный try С++ использует для stack unwind при исключениях пометки в “общем” стеке CPython использует для этих целей block stack. “Внутренности” CPython, часть вторая 13
  • 37. Block stack Block stack хранит в себе пары вида (адрес, глубина стека) “Внутренности” CPython, часть вторая 14
  • 38. Block stack Block stack хранит в себе пары вида (адрес, глубина стека) Инструкции вроде break “откручивают” value stack до запомненного значения глубины и делают goto на указанный адрес в байткоде “Внутренности” CPython, часть вторая 14
  • 39. Block stack Block stack хранит в себе пары вида (адрес, глубина стека) Инструкции вроде break “откручивают” value stack до запомненного значения глубины и делают goto на указанный адрес в байткоде Давайте посмотрим как это выглядит “Внутренности” CPython, часть вторая 14
  • 40. Block stack, пример def f(): while 1: return 2; continue; break 0 SETUP_LOOP 8 (to 11) >> 3 LOAD_CONST 1 (2) 6 RETURN_VALUE 7 BREAK_LOOP 8 JUMP_ABSOLUTE 3 >> 11 LOAD_CONST 0 (None) 14 RETURN_VALUE “Внутренности” CPython, часть вторая 15
  • 41. ceval.c case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, STACK_LEVEL()); continue; “Внутренности” CPython, часть вторая 16
  • 42. ceval.c, BREAK case BREAK_LOOP: why = WHY_BREAK; goto fast_block_end; fast_block_end: while (why != WHY_NOT && f->f_iblock > 0) { PyTryBlock *b = PyFrame_BlockPop(f); if (b->b_type == SETUP_LOOP && why == WHY_BREAK) { why = WHY_NOT; JUMPTO(b->b_handler); break; } “Внутренности” CPython, часть вторая 17
  • 43. Другие хранилища Помимо value stack и block stack, нужно еще хранить адреса возврата, локальные переменные, лексическое замыкание “Внутренности” CPython, часть вторая 18
  • 44. Другие хранилища Помимо value stack и block stack, нужно еще хранить адреса возврата, локальные переменные, лексическое замыкание В прошлой части этой презентации рассказывалось, что локальные переменные определяются на этапе компиляции и для них заводится список фиксированного размера с обращением по индексу за O(1) “Внутренности” CPython, часть вторая 18
  • 45. Другие хранилища Помимо value stack и block stack, нужно еще хранить адреса возврата, локальные переменные, лексическое замыкание В прошлой части этой презентации рассказывалось, что локальные переменные определяются на этапе компиляции и для них заводится список фиксированного размера с обращением по индексу за O(1) Аналогично компилятор (в байткод) поступает и с лексическим замыканием “Внутренности” CPython, часть вторая 18
  • 46. Другие хранилища Помимо value stack и block stack, нужно еще хранить адреса возврата, локальные переменные, лексическое замыкание В прошлой части этой презентации рассказывалось, что локальные переменные определяются на этапе компиляции и для них заводится список фиксированного размера с обращением по индексу за O(1) Аналогично компилятор (в байткод) поступает и с лексическим замыканием Кроме того, code object может вызвать сам себя (рекурсия?) и тогда обоим экземплярам нужны свои стеки. “Внутренности” CPython, часть вторая 18
  • 47. frame object Является хранилищем состояния для конкретного code object “Внутренности” CPython, часть вторая 19
  • 48. frame object Является хранилищем состояния для конкретного code object Без code object не имеет смысла - все его параметры определяются атрибутами исполняемого кода “Внутренности” CPython, часть вторая 19
  • 49. frame object Является хранилищем состояния для конкретного code object Без code object не имеет смысла - все его параметры определяются атрибутами исполняемого кода Включает в себя value stack, block stack, locals, cellvars “Внутренности” CPython, часть вторая 19
  • 50. frame object Является хранилищем состояния для конкретного code object Без code object не имеет смысла - все его параметры определяются атрибутами исполняемого кода Включает в себя value stack, block stack, locals, cellvars Ссылается на предыдущий фрейм в стеке “Внутренности” CPython, часть вторая 19
  • 51. frame object frame object - полный аналог activation frame в С “Внутренности” CPython, часть вторая 20
  • 52. frame object frame object - полный аналог activation frame в С Только в C activation frame расположен на общем стеке - адреса возврата и локальные переменные идут “вперемешку”, и activation frame волей-неволей уничтожается при выходе из функции (последующие вызовы других функций его перетрут). “Внутренности” CPython, часть вторая 20
  • 53. frame object frame object - полный аналог activation frame в С Только в C activation frame расположен на общем стеке - адреса возврата и локальные переменные идут “вперемешку”, и activation frame волей-неволей уничтожается при выходе из функции (последующие вызовы других функций его перетрут). В frame object есть ссылка f_back на предыдущий фрейм в стеке, поэтому в CPython стек вызовов реализован как односвязный список. “Внутренности” CPython, часть вторая 20
  • 54. Почему односвязный список? В отличие от contiguous представления стека в C, это позволяет продлевать время жизни фрейма сколь угодно долго. “Внутренности” CPython, часть вторая 21
  • 55. Почему односвязный список? В отличие от contiguous представления стека в C, это позволяет продлевать время жизни фрейма сколь угодно долго. Каждый фрейм выделяется и освобождается как обычный PyObject, в подходящем месте в памяти, совершенно необязательно кого-то перетирать. “Внутренности” CPython, часть вторая 21
  • 56. Почему односвязный список? В отличие от contiguous представления стека в C, это позволяет продлевать время жизни фрейма сколь угодно долго. Каждый фрейм выделяется и освобождается как обычный PyObject, в подходящем месте в памяти, совершенно необязательно кого-то перетирать. Это позволяет реализовать генераторы. “Внутренности” CPython, часть вторая 21
  • 57. Генераторы Это просто стек (в виде списка) фреймов, завернутый в объект (genobject). “Внутренности” CPython, часть вторая 22
  • 58. Генераторы Это просто стек (в виде списка) фреймов, завернутый в объект (genobject). yield приостанавливает его выполнение, next() возобновляет c того места, где в последний раз был вызван yield “Внутренности” CPython, часть вторая 22
  • 59. Генераторы Это просто стек (в виде списка) фреймов, завернутый в объект (genobject). yield приостанавливает его выполнение, next() возобновляет c того места, где в последний раз был вызван yield Стек фреймов живет столько, сколько живет genobject. “Внутренности” CPython, часть вторая 22
  • 60. Генераторы и фреймы code 1 code 2 code gencode 3 code 4 genobject f_code f_back f_code locals f_back f_code f_back f_code f_back f_code f_back f_code f_back f_code f_back f_code f_back “Внутренности” CPython, часть вторая 23
  • 61. Генераторы Генераторы в CPython не столь общи, как хотелось бы “Внутренности” CPython, часть вторая 24
  • 62. Генераторы Генераторы в CPython не столь общи, как хотелось бы Во-первых, yield это statement, а не expression “Внутренности” CPython, часть вторая 24
  • 63. Генераторы Генераторы в CPython не столь общи, как хотелось бы Во-первых, yield это statement, а не expression Во-вторых, yield возможен только в самой функции-генераторе, нo не в вызываемых ею “Внутренности” CPython, часть вторая 24
  • 64. Генераторы Генераторы в CPython не столь общи, как хотелось бы Во-первых, yield это statement, а не expression Во-вторых, yield возможен только в самой функции-генераторе, нo не в вызываемых ею Оба ограничения нефундаментальны “Внутренности” CPython, часть вторая 24
  • 65. Генераторы - альтернативы PEP 380 - официально принятый для Python 3 пропоузал, который позволит реализовывать полноценные сопрограммы на генераторах (как, например, в Lua) “Внутренности” CPython, часть вторая 25
  • 66. Генераторы - альтернативы PEP 380 - официально принятый для Python 3 пропоузал, который позволит реализовывать полноценные сопрограммы на генераторах (как, например, в Lua) greenlet - нативный модуль расширения для CPython, реализующий кооперативную многозадачность через “срезание” сишного стека “Внутренности” CPython, часть вторая 25
  • 67. Генераторы - альтернативы PEP 380 - официально принятый для Python 3 пропоузал, который позволит реализовывать полноценные сопрограммы на генераторах (как, например, в Lua) greenlet - нативный модуль расширения для CPython, реализующий кооперативную многозадачность через “срезание” сишного стека stackless - форк CPython, развивающий идею “фреймы как объекты” до полноценной кооперативной многозадачности “Внутренности” CPython, часть вторая 25
  • 69. Объектная модель Ранее мы уже упоминали, что все с точки зрения CPython есть PyObject “Внутренности” CPython, часть вторая 27
  • 70. Объектная модель Ранее мы уже упоминали, что все с точки зрения CPython есть PyObject Также мы знаем, что в байткоде инструкция BINARY_ADD удаляет два объекта с вершины стека, складывает их, после чего помещает результат на вершину стека “Внутренности” CPython, часть вторая 27
  • 71. Объектная модель Ранее мы уже упоминали, что все с точки зрения CPython есть PyObject Также мы знаем, что в байткоде инструкция BINARY_ADD удаляет два объекта с вершины стека, складывает их, после чего помещает результат на вершину стека Сложение для чисел - это сложение, для строк - конкатенация, и вообще мы можем переопределить __add__ у чего угодно “Внутренности” CPython, часть вторая 27
  • 72. Объектная модель Ранее мы уже упоминали, что все с точки зрения CPython есть PyObject Также мы знаем, что в байткоде инструкция BINARY_ADD удаляет два объекта с вершины стека, складывает их, после чего помещает результат на вершину стека Сложение для чисел - это сложение, для строк - конкатенация, и вообще мы можем переопределить __add__ у чего угодно Как интерпретатор узнает, что делать? “Внутренности” CPython, часть вторая 27
  • 73. Type object, слоты, протоколы В самом начале мы упомянули, что у PyObject обязательно присутствует поле ob_type - ссылка на type object “Внутренности” CPython, часть вторая 28
  • 74. Type object, слоты, протоколы В самом начале мы упомянули, что у PyObject обязательно присутствует поле ob_type - ссылка на type object Оказывается, в type object есть слоты, возвращающие реализации требуемых операций (если те поддерживаются объектом, само собой) “Внутренности” CPython, часть вторая 28
  • 75. Type object, слоты, протоколы В самом начале мы упомянули, что у PyObject обязательно присутствует поле ob_type - ссылка на type object Оказывается, в type object есть слоты, возвращающие реализации требуемых операций (если те поддерживаются объектом, само собой) Интерпретатор просто вызывает нужные функции по указателям, либо возвращает ошибку несовместимости типов. “Внутренности” CPython, часть вторая 28
  • 76. Type object, слоты, протоколы В самом начале мы упомянули, что у PyObject обязательно присутствует поле ob_type - ссылка на type object Оказывается, в type object есть слоты, возвращающие реализации требуемых операций (если те поддерживаются объектом, само собой) Интерпретатор просто вызывает нужные функции по указателям, либо возвращает ошибку несовместимости типов. Рассмотрим на примере int object. “Внутренности” CPython, часть вторая 28
  • 77. ceval.c case BINARY_ADD: w = POP(); v = TOP(); .... else { slow_add: x = PyNumber_Add(v, w); } ... SET_TOP(x); “Внутренности” CPython, часть вторая 29
  • 78. abstract.c PyObject * PyNumber_Add(PyObject *v, PyObject *w) { PyObject *result = binary_op1(v, w, NB_SLOT(nb_add)); ... return result; } “Внутренности” CPython, часть вторая 30
  • 79. abstract.c static PyObject *binary_op1(PyObject *v, PyObject *w, const int op_slot) { binaryfunc slotv = NULL; ... slotv = NB_BINOP(v->ob_type->tp_as_number, op_slot); ... if (slotv) { x = slotv(v, w); if (x != Py_NotImplemented) return x; “Внутренности” CPython, часть вторая 31
  • 80. intobject.c static PyObject * int_add(PyIntObject *v, PyIntObject *w) { register long a, b, x; CONVERT_TO_LONG(v, a); CONVERT_TO_LONG(w, b); .... x = (long)((unsigned long)a + b); if ((x^a) >= 0 || (x^b) >= 0) return PyInt_FromLong(x); .... “Внутренности” CPython, часть вторая 32
  • 81. Слоты и протоколы Слоты и протоколы - это довольно низкоуровневая особенность, которая из кода на Python не видна “Внутренности” CPython, часть вторая 33
  • 82. Слоты и протоколы Слоты и протоколы - это довольно низкоуровневая особенность, которая из кода на Python не видна Как она сочетается с наследованием и возможностью переопределения через “магические” имена (вроде __add__?) “Внутренности” CPython, часть вторая 33
  • 83. Слоты и протоколы Слоты и протоколы - это довольно низкоуровневая особенность, которая из кода на Python не видна Как она сочетается с наследованием и возможностью переопределения через “магические” имена (вроде __add__?) В этом проявляется красота объектной модели Python. “Внутренности” CPython, часть вторая 33
  • 84. type object == class type object и классы - одно и то же. “Внутренности” CPython, часть вторая 34
  • 85. type object == class type object и классы - одно и то же. (За исключением old style classes, которые все являются объектами типа instance и фактически существуют только ради совместимости с legacy кодом на Python < 2.5) “Внутренности” CPython, часть вторая 34
  • 86. type object == class type object и классы - одно и то же. (За исключением old style classes, которые все являются объектами типа instance и фактически существуют только ради совместимости с legacy кодом на Python < 2.5) При создании класса создается новый type object, который наполняется содержимым из классов-родителей. “Внутренности” CPython, часть вторая 34
  • 87. type object == class При наследовании классов все слоты type object копируются в новый класс (typeobject.c): static PyObject * type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { ... /* Put the proper slots in place */ fixup_slot_dispatchers(type); “Внутренности” CPython, часть вторая 35
  • 88. type object == class При попытке переопределить метод в рантайме через выставление “магического” атрибута класса в дело включается type_setattro, определенный в слоте tp_setattro у типа класса “Внутренности” CPython, часть вторая 36
  • 89. type object == class При попытке переопределить метод в рантайме через выставление “магического” атрибута класса в дело включается type_setattro, определенный в слоте tp_setattro у типа класса Да, у type object тоже есть тип, и это тоже type object :) “Внутренности” CPython, часть вторая 36
  • 90. type object == class При попытке переопределить метод в рантайме через выставление “магического” атрибута класса в дело включается type_setattro, определенный в слоте tp_setattro у типа класса Да, у type object тоже есть тип, и это тоже type object :) type_setattro знает про слоты и правильно их обновляет: static int type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) { ... return update_slot(type, name); “Внутренности” CPython, часть вторая 36
  • 91. type object == class Кроме того, технические поля инстанса (вроде __dict__), также являются с точки зрения типа обычными аттрибутами “Внутренности” CPython, часть вторая 37
  • 92. type object == class Кроме того, технические поля инстанса (вроде __dict__), также являются с точки зрения типа обычными аттрибутами Вкупе с дескрипторами, про которые много кто уже здесь говорил, это дает поистине впечатляющие возможности “Внутренности” CPython, часть вторая 37
  • 93. type object == class Кроме того, технические поля инстанса (вроде __dict__), также являются с точки зрения типа обычными аттрибутами Вкупе с дескрипторами, про которые много кто уже здесь говорил, это дает поистине впечатляющие возможности В частности, практически ко всему, во что можно впихнуть заголовок PyObject, можно предоставить идиоматичную питоновскую обертку, не меняя представления “Внутренности” CPython, часть вторая 37
  • 94. type object == class Кроме того, технические поля инстанса (вроде __dict__), также являются с точки зрения типа обычными аттрибутами Вкупе с дескрипторами, про которые много кто уже здесь говорил, это дает поистине впечатляющие возможности В частности, практически ко всему, во что можно впихнуть заголовок PyObject, можно предоставить идиоматичную питоновскую обертку, не меняя представления Это обуславливает такое количество библиотек - делать интерфейсы для C/C++ библиотек довольно легко “Внутренности” CPython, часть вторая 37
  • 95. slots Чтобы поменять представление объекта в памяти, необязательно лезть на уровень Python/C API “Внутренности” CPython, часть вторая 38
  • 96. slots Чтобы поменять представление объекта в памяти, необязательно лезть на уровень Python/C API Для объектов, которые создаются миллионами и редко меняют набор полей, есть встроенная возможность избежать создания __dict__ для каждого инстанса. “Внутренности” CPython, часть вторая 38
  • 97. slots Чтобы поменять представление объекта в памяти, необязательно лезть на уровень Python/C API Для объектов, которые создаются миллионами и редко меняют набор полей, есть встроенная возможность избежать создания __dict__ для каждого инстанса. Для этого в классе надо объявить атрибут __slots__, и в нем объявить имена полей. “Внутренности” CPython, часть вторая 38
  • 98. slots Чтобы поменять представление объекта в памяти, необязательно лезть на уровень Python/C API Для объектов, которые создаются миллионами и редко меняют набор полей, есть встроенная возможность избежать создания __dict__ для каждого инстанса. Для этого в классе надо объявить атрибут __slots__, и в нем объявить имена полей. Тогда все инстансы будут хранить только ссылки на значения атрибутов в определенном порядке, __dict__ будет создан только при попытке выставить атрибут не из __slots__. “Внутренности” CPython, часть вторая 38
  • 99. slots >>> class SlotClass: __slots__ = "x", "y" >>> X = SlotClass() >>> X.x = 1; X.y = 2 >>> asizeof(X) 128 >>> class DictClass: pass >>> Y = DictClass() >>> Y.x = 1; Y.y = 2 >>> asizeof(Y) 480 “Внутренности” CPython, часть вторая 39
  • 101. Заключение Напоследок хочу напомнить, что все рассказанное может быть почерпнуто прямо из исходников CPython - они хорошо задокументированы и читаются довольно легко “Внутренности” CPython, часть вторая 41
  • 102. Заключение Напоследок хочу напомнить, что все рассказанное может быть почерпнуто прямо из исходников CPython - они хорошо задокументированы и читаются довольно легко Лезть в исходники интерпретатора чтобы понять, как ведет себя прикладной код - вполне себе реальный сценарий “Внутренности” CPython, часть вторая 41
  • 103. Заключение Напоследок хочу напомнить, что все рассказанное может быть почерпнуто прямо из исходников CPython - они хорошо задокументированы и читаются довольно легко Лезть в исходники интерпретатора чтобы понять, как ведет себя прикладной код - вполне себе реальный сценарий Если тема доклада вас заинтересовала, то от себя хочу порекомендовать следующие ресурсы “Внутренности” CPython, часть вторая 41
  • 104. “Python Innards”, Yaniv Aknin http://en.wordpress.com/tag/pythons-innards/ Серия постов от Yaniv Aknin про байткод, стеки, thread state и объектную модель в CPython. “Внутренности” CPython, часть вторая 42
  • 105. “Python internals”, Eli Bendersky http://tinyurl.com/pyinternals Серия постов от Eli Bendersky про компилятор Python, а также объектную модель Python 3. “Внутренности” CPython, часть вторая 43
  • 106. “Understanding the Python GIL”, David Beazley http://www.dabeaz.com/GIL/ Презентации David Beazley, касающиеся особенностей реализации GIL в Python, проливающие свет на его неочевидное поведение (например, существенное замедление CPU-bound многопоточного кода на многоядерных машинах) “Внутренности” CPython, часть вторая 44