Лучший курс по Python 9: Переменные
https://www.youtube.com/watch?v=crSzQKfevZU
Я хотел сделать видео про переменные, которое бы рассказывало: а как на самом деле происходит создание и поиск имени? Все рассказывают про переменные, как про какие "коробки" для значений. А не они не коробки! Потому, в видео про переменные я рассказываю:
- Что никаких переменных в Python – нет 🌚
- Про
- Про генерацию байткода: покрываем все стадии через
- Про замыкания с
- Ну и про рантайм конечно же! Как работает, например
Бонус! Я показывал видео Грише Петрову до публикации. Он дал ценную обратную связь: я не упомянул, почему иногда модификация
-
На самом деле
будет делать
И изменения видны не будут.
- А вот тут я пропустил шаг: так а почему на уровне модуля / REPL оно работает?
Потому что в REPL / модуле
Где
- Далее, на слайде я показываю, но повторю данную мысль еще раз:
Не надо так! Не модифицируйте скоупы, просто потому что можно!
Надеюсь, что было интересно.
Поддержать такой контент можно тут:
- https://boosty.to/sobolevn
- https://github.com/sponsors/wemake-services
#lkpp
https://www.youtube.com/watch?v=crSzQKfevZU
Я хотел сделать видео про переменные, которое бы рассказывало: а как на самом деле происходит создание и поиск имени? Все рассказывают про переменные, как про какие "коробки" для значений. А не они не коробки! Потому, в видео про переменные я рассказываю:
- Что никаких переменных в Python – нет 🌚
- Про
frame.f_locals и frame.f_globals- Про генерацию байткода: покрываем все стадии через
symtable.c / compile.c / codegen.c- Про замыкания с
.__closure__ и MAKE_CELL- Ну и про рантайм конечно же! Как работает, например
globals() и locals() на самом деле
/*[clinic input]
globals as builtin_globals
Return the dictionary containing the current scope's global variables.
NOTE: Updates to this dictionary *will* affect name lookups in the current
global scope and vice-versa.
[clinic start generated code]*/
static PyObject *
builtin_globals_impl(PyObject *module)
/*[clinic end generated code: output=e5dd1527067b94d2 input=9327576f92bb48ba]*/
{
PyObject *d;
d = PyEval_GetGlobals();
return Py_XNewRef(d);
}
Бонус! Я показывал видео Грише Петрову до публикации. Он дал ценную обратную связь: я не упомянул, почему иногда модификация
locals().update() работает, а иногда нет. Исправляюсь!-
locals(), как показано в видео, обычно возвращает новый dict, потому что использует прокси внутри C. Внутри функции модификация locals() работать не будет. И вот почему, код:
// PyObject * _PyEval_GetFrameLocals(void)
if (PyFrameLocalsProxy_Check(locals)) {
PyObject* ret = PyDict_New();
if (ret == NULL) {
Py_DECREF(locals);
return NULL;
}
if (PyDict_Update(ret, locals) < 0) {
Py_DECREF(ret);
Py_DECREF(locals);
return NULL;
}
Py_DECREF(locals);
return ret;
}
assert(PyMapping_Check(locals));
return locals;
На самом деле
def some():
locals().update({'a': 1})
print(a)
будет делать
.update на *другом* dict объекте, который мы создали из PyFrameLocalsProxy, а не сам прокси.И изменения видны не будут.
- А вот тут я пропустил шаг: так а почему на уровне модуля / REPL оно работает?
Потому что в REPL / модуле
frame.f_locals is frame.f_globals. Вот код:
static int
PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,
PyCompilerFlags *flags)
{
PyArena *arena = _PyArena_New();
if (arena == NULL) {
return -1;
}
mod_ty mod;
PyObject *interactive_src;
int parse_res = pyrun_one_parse_ast(fp, filename, flags, arena, &mod, &interactive_src);
PyObject *main_module = PyImport_AddModuleRef("__main__");
PyObject *main_dict = PyModule_GetDict(main_module); // borrowed ref
PyObject *res = run_mod(mod, filename, main_dict, main_dict, flags, arena, interactive_src, 1);
// ...
Где
static PyObject *
run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,
PyCompilerFlags *flags, PyArena *arena, PyObject* interactive_src,
int generate_new_source)
{
- Далее, на слайде я показываю, но повторю данную мысль еще раз:
NOTE: Whether or not updates to this dictionary will affect name lookups in
the local scope and vice-versa is *implementation dependent* and not
covered by any backwards compatibility guarantees.
Не надо так! Не модифицируйте скоупы, просто потому что можно!
Надеюсь, что было интересно.
Поддержать такой контент можно тут:
- https://boosty.to/sobolevn
- https://github.com/sponsors/wemake-services
#lkpp
YouTube
Лучший курс по Python 9: Переменные
Лучший курс по питону: 9
Или "обзор исходников CPython с CPython core разработчиком".
Тема: переменные
- Что такое "переменная" в Python?
- Есть ли в Python "переменные"?
- Чем "переменная" отличается от "имени"?
- Что такое `locals()` и `globals()` в Python?…
Или "обзор исходников CPython с CPython core разработчиком".
Тема: переменные
- Что такое "переменная" в Python?
- Есть ли в Python "переменные"?
- Чем "переменная" отличается от "имени"?
- Что такое `locals()` и `globals()` в Python?…
3🔥57❤19👍10🤔1🤯1
Лучший курс по Python 12: tuple
https://youtube.com/watch?v=P5OY3Y4Fc7k
Я решил окончательно упороться: сделал видео про
- В чем разница между tuple и list?
- Аннотации tuple
- Тип произведение
- TypeVarTuple, PEP646, Unpack
Для мидлов:
- ast.Tuple
- tuple_iterator
- collections.abc
- collections.namedtuple
- typing.NamedTuple
Для сениоров:
- PyTupleObject
- PyVarObject
- tp_alloc, tp_dealloc, freelists
-
-
- Мутабельность tuple
- PyTuple_Pack, Py_BuildValue
- Виртуальная машина и компилятор: BUILD_TUPLE
- INTRINSIC_LIST_TO_TUPLE
- Оптимизации компилятора
- PySequenceTuple
Обещанный бонус
В видео я обещал, что расскажу в тг, что такое
Документация и исходники: https://github.com/python/cpython/blob/d05140f9f77d7dfc753dd1e5ac3a5962aaa03eff/Include/cpython/object.h#L431-L507
По факту - данные два макроса представляют собой
По сути, мы просто при достижении определенного "большого" значения (50) перестаем выполнять деаллокацию напрямую, просто добавляем объекты в список для деаллокации на потом. Вот и вся хитрость!
Завершение
Если вам нравится мой технический контент – его всегда можно поддержать:
- Материально
- Морально: поделиться с вашими коллегами, чтобы они тоже знали все про кортежи :)
#lkpp
| Поддержать | YouTube | GitHub | Чат |
https://youtube.com/watch?v=P5OY3Y4Fc7k
Я решил окончательно упороться: сделал видео про
tuple на 1ч 30м. Зато я рассказал про tuple вообще все, что знал сам. Для джунов:- В чем разница между tuple и list?
- Аннотации tuple
- Тип произведение
- TypeVarTuple, PEP646, Unpack
Для мидлов:
- ast.Tuple
- tuple_iterator
- collections.abc
- collections.namedtuple
- typing.NamedTuple
Для сениоров:
- PyTupleObject
- PyVarObject
- tp_alloc, tp_dealloc, freelists
-
__len__-
__hash__- Мутабельность tuple
- PyTuple_Pack, Py_BuildValue
- Виртуальная машина и компилятор: BUILD_TUPLE
- INTRINSIC_LIST_TO_TUPLE
- Оптимизации компилятора
- PySequenceTuple
Обещанный бонус
В видео я обещал, что расскажу в тг, что такое
Py_TRASHCAN_BEGIN и Py_TRASHCAN_END. Документация и исходники: https://github.com/python/cpython/blob/d05140f9f77d7dfc753dd1e5ac3a5962aaa03eff/Include/cpython/object.h#L431-L507
По факту - данные два макроса представляют собой
do/while цикл, который позволяет более удобно управлять сборкой "контейнеров" (tuple, в нашем случае). Каждый объект внутри "контейнера" может тоже быть контейнером. Таким образом про Py_DECREF(op->ob_item[i]) можно начать каскадную деаллокацию объектов внутри. И мы можем столкнуться с переполнением стека вызовов.
#define Py_TRASHCAN_BEGIN(op, dealloc) \
do { \
PyThreadState *tstate = PyThreadState_Get(); \
if (tstate->c_recursion_remaining <= Py_TRASHCAN_HEADROOM && Py_TYPE(op)->tp_dealloc == (destructor)dealloc) { \
_PyTrash_thread_deposit_object(tstate, (PyObject *)op); \
break; \
} \
tstate->c_recursion_remaining--;
/* The body of the deallocator is here. */
#define Py_TRASHCAN_END \
tstate->c_recursion_remaining++; \
if (tstate->delete_later && tstate->c_recursion_remaining > (Py_TRASHCAN_HEADROOM*2)) { \
_PyTrash_thread_destroy_chain(tstate); \
} \
} while (0);
По сути, мы просто при достижении определенного "большого" значения (50) перестаем выполнять деаллокацию напрямую, просто добавляем объекты в список для деаллокации на потом. Вот и вся хитрость!
Завершение
Если вам нравится мой технический контент – его всегда можно поддержать:
- Материально
- Морально: поделиться с вашими коллегами, чтобы они тоже знали все про кортежи :)
#lkpp
| Поддержать | YouTube | GitHub | Чат |
YouTube
Лучший курс по Python 12: tuple
Лучший курс по питону: 12
Или "обзор исходников CPython с CPython core разработчиком".
Тема: tuple
00:00 Вступление
00:53 Junior
01:24 В чем разница между tuple и list?
07:54 Аннотации tuple
11:05 Тип произведение
14:14 TypeVarTuple, PEP646, Unpack
22:29…
Или "обзор исходников CPython с CPython core разработчиком".
Тема: tuple
00:00 Вступление
00:53 Junior
01:24 В чем разница между tuple и list?
07:54 Аннотации tuple
11:05 Тип произведение
14:14 TypeVarTuple, PEP646, Unpack
22:29…
253🔥170👍24❤10😱8