Ответ 1
-----------
Отказ от ответственности:
Документация в этом ответе не является официальной и может быть неправильной.
Этот ответ действителен только для версии python 3.x
-----------
Чтобы создать объект кода, вы должны передать функции CodeType() следующие аргументы:
CodeType(
argcount, # integer
kwonlyargcount, # integer
nlocals, # integer
stacksize, # integer
flags, # integer
codestring, # bytes
consts, # tuple
names, # tuple
varnames, # tuple
filename, # string
name, # string
firstlineno, # integer
lnotab, # bytes
freevars, # tuple
cellvars # tuple
)
Теперь я попытаюсь объяснить, в чем смысл каждого аргумента.
argcount
Количество аргументов, которые должны быть переданы функции (* args и ** kwargs, не включены).
kwonlyargcount
Число аргументы только для ключевого слова.
nlocals
Число локальных переменных,
а именно все переменные и параметры (* args и ** kwargs включены), кроме глобальных имен.
STACKSIZE
Количество стека (стек виртуальной машины), требуемое кодом,
если вы хотите понять, как это работает, см. официальную Документация.
флаги
Растровое изображение, которое говорит что-то о объекте кода:
1 → оптимизирован код
2 → newlocals: существует новое локальное пространство имен (например, функция)
4 → код принимает произвольное число позиционных аргументов (используется * args)
8 → код принимает произвольное число аргументов с ключевыми словами (используется * kwargs)
32 → код является генератором
othes используются в более старых версиях python или активируются, чтобы сказать, что импортировано из __ будущего __
codestring
Последовательность байтов, представляющая инструкции байткода
если вы хотите получить лучшее понимание, см. Документация (такая же, как указано выше)
consts
Кортеж, содержащий литералы, используемые байт-кодом (например, предварительно вычисленные числа, кортежи и строки)
имена
Кортеж, содержащий имена, используемые байт-кодом
эти имена являются глобальными переменными, функциями и классами, а также атрибутами, загружаемыми из объектов
имени переменной
Кортеж, содержащий локальные имена, используемые байтовым кодом (сначала аргументы, затем локальные переменные)
имя_файла
Это имя файла, из которого был скомпилирован код.
Это может быть то, что вы хотите, вы можете лгать об этом.;)
имя
Он дает имя функции.
Также это может быть все, что вы хотите, но будьте осторожны:
это имя показано в трассировке, если имя нечеткое, трассировка может быть неясной,
просто подумайте о том, как лямбды могут раздражать.
firstlineno
Первая строка функции (для цели отладки, если вы скомпилировали исходный код)
lnotab
Отображение байтов, которое коррелирует смещение байт-кода с номерами строк.
(я думаю, что это также касается отладочной цели, документации об этом немного)
freevars
Кортеж, содержащий имена свободных переменных.
Свободные переменные - это переменные, объявленные в пространстве имен, где был определен объект кода,
они используются при объявлении вложенных функций.
это не происходит на уровне модуля, потому что в этом случае свободные переменные также являются глобальными переменными.
cellvars
Кортеж, содержащий имена локальных переменных, на которые ссылаются вложенные функции.
------------
Примеры:
следующие примеры должны разъяснять смысл сказанного выше.
Примечание: в атрибутах завершенных объектов кода, упомянутых выше, есть префикс co_,
и функция сохраняет свой исполняемый объект в атрибуте ___ код __
------------
1-й пример
def F(a,b):
global c
k=a*c
w=10
p=(1,"two",3)
print(F.__code__.co_argcount)
print(F.__code__.co_nlocals , F.__code__.co_varnames)
print(F.__code__.co_stacksize)
print(F.__code__.co_flags)
print(F.__code__.co_names)
print(F.__code__.co_consts)
Вывод:
2
5 ('a', 'b', 'k', 'w', 'p')
3
67
('c' ,)
(None, 10, 1, 'two'. 3, (1, 'two', 3))
-
есть два аргумента, переданных этой функции ( "a", "b" )
-
эта функция имеет два параметра ( "a", "b" ) и три локальные переменные ( "k", "w", "p" )
-
разбор байт-кода функции мы получаем:
3 0 LOAD_FAST 0 (a) #stack: ["a"] 3 LOAD_GLOBAL 0 (c) #stack: ["a","c"] 6 BINARY_MULTIPLY #stack: [result of a*c] 7 STORE_FAST 2 (k) #stack: [] 4 10 LOAD_CONST 1 (10) #stack: [10] 13 STORE_FAST 3 (w) #stack: [] 5 16 LOAD_CONST 5 ((1, 'two', 3)) #stack: [(1,"two",3)] 19 STORE_FAST 4 (p) #stack: [] 22 LOAD_CONST 0 (None) #stack: [None] 25 RETURN_VALUE #stack: []
поскольку вы можете заметить, что chile выполняет функцию, у нас никогда не бывает более трех элементов в стеке (в этом случае кортеж рассчитывается как его длина)
-
Значение флага - dec 67 = bin 1000011 = bin 1000000 +10 +1 = dec 64 +2 +1, поэтому мы понимаем, что
- код оптимизирован (поскольку большая часть автоматически сгенерированного кода)
- при выполнении функции поменять местами локальное пространство имен байт-кода
- 64? На самом деле я не знаю, что это значит.
-
единственным глобальным именем, которое используется в функции, является "c", оно сохраняется в co_names
-
каждый явный литерал, который мы используем, хранится в co_consts:
- Нет - это возвращаемое значение функции
- мы явно присваиваем число 10 w
- мы явно присваиваем (1, 'two', 3) p
- если кортеж является константой, каждый элемент этого набора является константой, поэтому 1, "два", 3 являются константами
------------
Второй пример
ModuleVar="hi"
def F():
FunctionVar=106
UnusedVar=ModuleVar
def G():
return (FunctionVar,ModuleVar)
print(G.__code__.co_freevars)
print(G.__code__.co_names)
F()
print(F.__code__.co_cellvars)
print(F.__code__.co_freevars)
print(F.__code__.co_names)
Вывод:
('FunctionVar',)
('ModuleVar',)
('FunctionVar',)
()
('print', '__code__', 'co_freevars', 'co_names', 'ModuleVar')
Значение вывода таково:
первая и вторая строки печатаются, когда F выполняется, поэтому они показывают co_freevars и co_names из G-кода:
"FunctionVar" находится в пространстве имен функции F, где G было создано,
"ModuleVar" вместо этого является переменной модуля, поэтому он считается глобальным.
следующие три строки относятся к символам co_cellvars, co_freevars и co_names F-кода:
"ФункцияVar" ссылается в G-вложенной функции, поэтому она помечена как cellvar,
"ModuleVar" находится в пространстве имен, где F был создан, но это модульная переменная,
поэтому он не помечен как freevar, но он встречается в глобальных именах.
также встроенная функция print отмечена в именах, и все имена атрибутов, используемые в F.
------------
3-й пример
Это инициализация рабочего кода кода,
это не полезно, но вы можете делать все, что хотите, с помощью этой функции.
MyCode= CodeType(
0,
0,
0,
3,
64,
bytes([101, 0, 0, #Load print function
101, 1, 0, #Load name 'a'
101, 2, 0, #Load name 'b'
23, #Take first two stack elements and store their sum
131, 1, 0, #Call first element in the stack with one positional argument
1, #Pop top of stack
101, 0, 0, #Load print function
101, 1, 0, #Load name 'a'
101, 2, 0, #Load name 'b'
20, #Take first two stack elements and store their product
131, 1, 0, #Call first element in the stack with one positional argument
1, #Pop top of stack
100, 0, 0, #Load constant None
83]), #Return top of stack
(None,),
('print', 'a', 'b'),
(),
'PersonalCodeObject',
'MyCode',
1,
bytes([14,1]),
(),
() )
a=2
b=3
exec(MyCode) # code prints the sum and the product of "a" and "b"
Вывод:
5
6