Arahan ini digunakan untuk memuatkan pemalar ke dalam tindanan. Pemalar boleh menjadi objek seperti nombor, rentetan, tupel, senarai, kamus, dll. Contohnya:
>>> dis.dis(lambda: 42) 1 0 LOAD_CONST 1 (42) 2 RETURN_VALUE
Arahan ini digunakan untuk memuatkan pembolehubah ke dalam tindanan. Contohnya:
>>> dis.dis(lambda: x) 1 0 LOAD_GLOBAL 0 (x) 2 RETURN_VALUE >>>
Arahan ini digunakan untuk menyimpan nilai pada bahagian atas tindanan ke dalam pembolehubah. Contohnya:
>>> dis.dis("x=42") 1 0 LOAD_CONST 0 (42) 2 STORE_NAME 0 (x) 4 LOAD_CONST 1 (None) 6 RETURN_VALUE
Arahan ini digunakan untuk menambah dua nilai pada bahagian atas tindanan dan menolak hasilnya ke tindanan.
>>> dis.dis(lambda: x + y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_ADD 6 RETURN_VALUE
Arahan ini digunakan untuk menolak dua nilai di bahagian atas tindanan dan menolak hasilnya ke tindanan.
>>> dis.dis(lambda: x - y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_SUBTRACT 6 RETURN_VALUE
Kod bait yang sama untuk penambahan, penolakan, pendaraban dan pembahagian untuk mendapatkan baki adalah seperti berikut:
>>> dis.dis(lambda: x + y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_ADD 6 RETURN_VALUE >>> dis.dis(lambda: x - y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_SUBTRACT 6 RETURN_VALUE >>> dis.dis(lambda: x * y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_MULTIPLY 6 RETURN_VALUE >>> dis.dis(lambda: x / y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_TRUE_DIVIDE 6 RETURN_VALUE >>> dis.dis(lambda: x // y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_FLOOR_DIVIDE 6 RETURN_VALUE >>> dis.dis(lambda: x % y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_MODULO 6 RETURN_VALUE
Arahan ini digunakan untuk membandingkan dua nilai di bahagian atas tindanan, dan Hasil perbandingan ditolak ke tindanan Parameter bait seterusnya selepas kod bait ini mewakili simbol perbandingan kurang daripada, lebih besar daripada, tidak sama dengan, dsb. Contohnya:
>>> dis.dis(lambda: x - y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 BINARY_SUBTRACT 6 RETURN_VALUE >>> dis.dis(lambda: x > y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 COMPARE_OP 4 (>) 6 RETURN_VALUE >>> dis.dis(lambda: x < y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 COMPARE_OP 0 (<) 6 RETURN_VALUE >>> dis.dis(lambda: x != y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 COMPARE_OP 3 (!=) 6 RETURN_VALUE >>> dis.dis(lambda: x <= y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 COMPARE_OP 1 (<=) 6 RETURN_VALUE >>> dis.dis(lambda: x >= y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 COMPARE_OP 5 (>=) 6 RETURN_VALUE >>> dis.dis(lambda: x == y) 1 0 LOAD_GLOBAL 0 (x) 2 LOAD_GLOBAL 1 (y) 4 COMPARE_OP 2 (==) 6 RETURN_VALUE
Patikkan elemen atas tindanan sebagai nilai pulangan.
Arahan ini digunakan untuk membuat senarai. Contohnya:
>>> dis.dis(lambda: [a, b, c, e]) 1 0 LOAD_GLOBAL 0 (a) 2 LOAD_GLOBAL 1 (b) 4 LOAD_GLOBAL 2 (c) 6 LOAD_GLOBAL 3 (e) 8 BUILD_LIST 4 10 RETURN_VALUE
Arahan bytecode ini mempunyai parameter yang menunjukkan bilangan elemen senarai dalam ruang tindanan Dalam contoh di atas, parameter ini ialah 4.
Arahan ini digunakan untuk mencipta tuple. Sebagai contoh:
>>> dis.dis(lambda: (a, b, c)) 1 0 LOAD_GLOBAL 0 (a) 2 LOAD_GLOBAL 1 (b) 4 LOAD_GLOBAL 2 (c) 6 BUILD_TUPLE 3 8 RETURN_VALUE
Bytecode yang sama juga mempunyai parameter yang menunjukkan bilangan elemen untuk mencipta tuple.
Arahan ini digunakan untuk mencipta kamus. Contohnya:
Seperti senarai dan tuple, arahan ini digunakan untuk mencipta objek koleksi Arahan yang sama juga mempunyai parameter yang menunjukkan bilangan elemen yang digunakan untuk mencipta koleksi.
>>> dis.dis(lambda: {a, b, c, d}) 1 0 LOAD_GLOBAL 0 (a) 2 LOAD_GLOBAL 1 (b) 4 LOAD_GLOBAL 2 (c) 6 LOAD_GLOBAL 3 (d) 8 BUILD_SET 4 10 RETURN_VALUE
Arahan ini digunakan untuk mencipta objek kamus Perintah yang sama juga mempunyai parameter yang menunjukkan bilangan elemen dalam kamus.
>>> dis.dis(lambda: {1:2, 3:4}) 1 0 LOAD_CONST 1 (2) 2 LOAD_CONST 2 (4) 4 LOAD_CONST 3 ((1, 3)) 6 BUILD_CONST_KEY_MAP 2 8 RETURN_VALUE
Jika anda seorang pythoner, maka anda pasti pernah mendengar tentang penghias lebih kurang Ini adalah gula sintaks ular sawa yang boleh kita Gunakan ia untuk melakukan banyak perkara menarik, seperti menambah beberapa fungsi pada fungsi tanpa mengubah suai kod sumber, seperti mengira masa.
import time def eval_time(func): def cal_time(*args, **kwargs): start = time.time() r = func(*args, **kwargs) end = time.time() return r, end - start return cal_time @eval_time def fib(n): a = 0 b = 1 while n > 0: n -= 1 a, b = b, a + b return a
Dalam kod di atas, kami melaksanakan fungsi untuk mengira jujukan Fibonacci Selain itu, kami juga menulis fungsi eval_time untuk mengira masa pelaksanaan fungsi tersebut output program adalah seperti berikut:
>>>fib(10)
(55, 5.9604644775390625e-06)
Anda boleh lihat Mencapai kesan yang kita inginkan.
Sekarang kita menggunakan contoh yang lebih mudah untuk mensimulasikan struktur kod di atas, supaya kita boleh menganalisis proses pelaksanaan fungsi di atas:
s = """ def decorator(func): print("Hello") return func @decorator def fib(n): pass """ dis.dis(s)
Keluaran fungsi dis di atas sepadan dengan bait kod Kod adalah seperti berikut:
<🎗条指令 MAKE_FUNCTION,这条字节码的作用是在虚拟机内部创建一个函数,函数的名称为 penghias,函数对应的字节码则是在先前数的名称为 penghias,函数对应的字节码则是在先前是在先前是压象,这条指令还会将创建好的函数对象压入栈中。 STORE_NAME,条字节码会将栈顶的元素弹出,并且将 co_names[oparg]码当中 co_names[oparg]就是 penghias 。LOAD_NAME,这条字节码就是将 co_names[oparg]空间当中,也就是上面的 penghias 函数加入进行栈空间当中。接下来的三条字节码 LOAD_CONST,LOAD_CONST 和和和和和和节码之后,栈空间如下所示:2 0 LOAD_CONST 0 (
执行完第二条指令 LOAD_CONST 之后,会将字符串 penghias 加载进入栈空间当中。", baris 2>)<🎜 1 ('penghias')
4 JADIKAN_FUNGSI 0
6 NAMA_KEDAI 0 (penghias)
6 8 LOAD_NAME <7 (penghias) LOAD_CONST 2 (", baris 6> )
12 LOAD_CONST 3 ('fib')
14 Make_Function 0
16 CALL_FUNCTION 1
18 Store_Name 1 (fib)
20 LOAD_CONST 4 (NONE)
pembongkaran & lt; kod penghias objek di 0x108068d40, fail "& lt; dis & gt;", baris 2 & gt ;:
3 0 load_global 0 (cetak)
2 load_const 1 ('hello') Call_function 1
6 POP_TOP
4 8 LOAD_FAST 0 (FUNC)
10 RETURN_VALUE
6>:
8 0 LOAD_CONST 0 (Tiada)
2 PULANGAN_NILAI
<万猡東一中这条指令主要是加载一个 objek kod 对象,这个对象里面主要是Penghias示:
接下来的一条指令非常重要,这条指令便是装饰器的核心原理,CALL_FUNCTION 这条指令有一个参数 i,在上面的字节码当中为 1,也就是说从栈顶开始的前 i 个元素都是函数参数,调用的函数在栈空间的位置为 i + 1 (从栈顶往下数),那么在上面的情况下就是说调用 decorator 函数,并且将 fib 函数作为 decorator 函数的参数,decorator 函数的返回值再压入栈顶。在上面的代码当中 decorator 函数返回值也是一个函数,也就是 decorator 函数的参数,即 fib 函数。
接下来便是 STORE_NAME 字节码,这条字节码的含义我们在前面已经说过了,就是将栈顶元素弹出,保存到 co_names[oparg] 指向的对象当中,在上面的代码当中也就是将栈顶的对象保存到 fib 当中。栈顶元素 fib 函数是调用函数 decorator 的返回值。
看到这里就能够理解了原来装饰器的最根本的原理不就是函数调用嘛,比如我们最前面的用于计算函数执行时间的装饰器的原理就是:
fib = eval_time(fib)
将 fib 函数作为 eval_time 函数的参数,再将这个函数的返回值保存到 fib 当中,当然这个对象必须是可调用的,不然后面使用 fib() 就会保存,我们可以使用下面的代码来验证这个效果。
def decorator(func): return func() @decorator def demo(): return "function demo return string : Demo" print(demo)
执行上面的程序结果为:
function demo return string : Demo
可以看到 demo 已经变成了一个字符串对象而不再是一个函数了,因为 demo = decorator(demo),而在函数 decorator 当中返回值是 demo 函数自己的返回值,因此才打印了字符串。
Atas ialah kandungan terperinci Bagaimana untuk melaksanakan penghias kod bait mesin maya Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!