Rumah >pembangunan bahagian belakang >Tutorial Python >Penghias Python - penghias penutup dan fungsi

Penghias Python - penghias penutup dan fungsi

PHPz
PHPzke hadapan
2023-04-10 14:51:071685semak imbas

1. Penutupan

Sebelum mempelajari penghias, anda perlu memahami konsep penutupan terlebih dahulu. Perkara utama dalam membentuk penutupan:

  • Fungsi bersarang
  • Gunakan fungsi dalam sebagai nilai pulangan bagi fungsi luar
  • Fungsi dalam mesti menggunakan pembolehubah bagi fungsi luar

Berikut ialah kes pengiraan purata senarai untuk menerangkan penutupan:

def make_average():
# 创建一个列表,用来保存数值
nums = []

# 定义一个内部函数,用来计算列表的平均值
def average(n):
# 将数值添加到列表中
nums.append(n)
# 返回平均值
return sum(nums) / len(nums)

return average
  1. Pertama, takrifkan fungsi make_average; 🎜>Kedua, dalam Tentukan senarai kosong dalam fungsi make_average untuk menyimpan nilai
  2. Sekali lagi, tentukan fungsi dalaman untuk mengira purata senarai
  3. Akhir sekali, gunakan fungsi dalaman ini sebagai fungsi luaran make_average Berhati-hati untuk tidak menambah () kepada nilai pulangan Menambah () menjadi panggilan fungsi ini.
Keputusannya adalah seperti berikut: apabila nilai yang diluluskan adalah 20, terdapat hanya satu nombor dalam senarai, jadi hasil pengiraan ialah 20 apabila nilai 30 diluluskan, nombor dalam senarai ialah Terdapat dua nombor 20 dan 30, jadi hasil pengiraan purata ialah 25.
# 调用外部函数,并将其复制给一个变量,注意:此时返回的是内函数的内存地址
a = make_average()
# 给这个变量加(),就相当于调用了内函数average
print(a(20))
print(a(30))

Penghias Python - penghias penutup dan fungsiPenghias

1. Pengenalan penghias

Sebagai contoh, terdapat dua fungsi berikut, yang mengira jumlah dua nombor dan skor masing-masing:

Sekarang ada keperluan: Saya ingin mencetak "Mula" sebelum pengiraan setiap fungsi bermula...", cetak "Pengiraan Tamat..." selepas pengiraan selesai. Kita boleh memenuhi keperluan ini dengan mengubah suai kod fungsi secara langsung, tetapi ini akan menghadapi masalah berikut:
def add(a, b):
"""计算两数之和"""
res = a + b
return res

def mul(a, b):
"""计算两数之积"""
res = a * b
return res

Jika terdapat terlalu banyak fungsi untuk diubah suai, sepuluh atau malah seratus fungsi, ia adalah tidak realistik;
  1. Ia tidak sesuai untuk penyelenggaraan kemudian. Contohnya, saya tidak mahu mencetak “Mulakan pengiraan...” tetapi cetak “mulakan...” Bukankah perlu mengubahnya semula ?
  2. Pelanggaran Prinsip Tertutup (OCP), iaitu reka bentuk program, memerlukan pembukaan lanjutan program dan menutup pengubahsuaian program itu; Oleh itu, kaedah di atas mengubah suai kod fungsi secara langsung tidak boleh dilaksanakan. Kami berharap dapat melanjutkan fungsi tanpa mengubah fungsi asal. Contohnya:
  3. Hasil pelaksanaan adalah seperti berikut:

def new_add(a, b):
print("开始计算...")
r = add(a, b)
print("计算结束...")
return r


print(new_add(22, 33))

Walaupun kaedah mencipta fungsi baharu ini tidak mengubah suai fungsi asal, ia menghadapi masalah yang sangat serius. Jika anda ingin memanjangkan fungsi mul, anda hanya boleh mencipta satu lagi fungsi sambungan; Jenis fungsi universal yang tidak mengubah kod fungsi asal ini ialah: penghias.

2. Penghias fungsi Penghias Python - penghias penutup dan fungsi

Penghias pada asasnya ialah fungsi atau kelas ular sawa, yang membolehkan fungsi atau kelas lain menambah fungsi tambahan tanpa membuat sebarang pengubahsuaian kod objek sedia ada Nilai pulangan penghias juga merupakan objek fungsi/kelas. Ia sering digunakan dalam senario dengan keperluan pemotongan silang, seperti: sisipan log, ujian prestasi, pemprosesan transaksi, caching, pengesahan kebenaran, dsb.

1) Fungsi yang dihias tidak mengambil parameter

Contohnya:

Hasil larian adalah seperti berikut:

Dapat dilihat bahawa tanpa mengubah kod fungsi asal, beberapa fungsi tambahan ditambah kepada fungsi asal ialah fungsi yang akan diubah suai ia dihantar ke dalam fungsi hiasan sebagai pembolehubah dan boleh digunakan secara universal untuk fungsi lain wrapper_info ini adalah penghias. Tetapi masalah semasa ialah, bagaimana jika fungsi yang dihias mengambil parameter? Contohnya:

def wrapper_info(func):
def inner():
print("开始介绍...")
res = func()
print("介绍结束...")
return res

return inner

def introduce1():
print("我是周润发,我来自HONG KONG")

info = wrapper_info(introduce1)
info()
2) Fungsi yang dihias mengambil parameter

Walaupun nama dan umur boleh dihantar dalam pembungkus_info penghias, bukan setiap fungsi yang dihias hanya mempunyai nama dan umur, atau parameter jenis tertentu, atau kamus, senarai, tuple, dsb. boleh dihantar masuk. Iaitu, apakah yang perlu saya lakukan jika jenis dan bilangan parameter yang diluluskan tidak ditetapkan?

Penghias Python - penghias penutup dan fungsiPada masa ini, anda perlu menggunakan parameter panjang berubah-ubah: (*args, **kwargs)

Contohnya:
def introduce2(name, age):
print(f"我叫{name}, 我今年{age}岁了")

Hasil berjalan adalah seperti berikut:

3)装饰器带参数

上述提到的是装饰器,一种是应用于被装饰的函数不带参数,一种是被装饰的函数带参数,那装饰器本身能否带参数呢?比如我定义一个变量,想通过传入不同的值来控制这个装饰器实现不同的功能。答案是肯定的,例如:

def use_log(level):
def decorator(func):
def inner(*args, **kwargs):
if level == "warn":
logging.warning("%s is running by warning" % func.__name__)
elif level == "info":
logging.warning("%s is running by info" % func.__name__)
else:
logging.warning("%s is running by other" % func.__name__)
return func(*args, **kwargs)

return inner

return decorator


def introduce4(name, age, city):
print(f"我叫{name}, 我今年{age}岁了, 我来自{city}")


info1 = use_log(introduce4('周星驰', 28, '香港'))
info1('info')
info2 = use_log(introduce4('周润发', 28, '香港'))
info2('warn')
info3 = use_log(introduce4('成龙', 28, '香港'))
info3('xxx')

运行结果如下:

Penghias Python - penghias penutup dan fungsi

3.装饰器调用

方式一:以函数方式调用

info3 = wrapper_info(introduce3)
info3('刘德华', 28, '香港')

如果是装饰器函数带参数,则调用方式为:

info4 = use_log(introduce4('周星驰', 28, '香港'))
info4('info')

方式二:以语法糖方式调用

即在被装饰函数上方以@符号进行修饰

@wrapper_info
def introduce3(name, age, city):
print(f"我叫{name}, 我今年{age}岁了, 我来自{city}")

introduce3('刘德华', 28, '香港')

如果是装饰器函数带参数,例如上述的use_log,则需要在装饰器中传入参数:

@use_log('info')
def introduce4(name, age, city):
print(f"我叫{name}, 我今年{age}岁了, 我来自{city}")

小结

什么是装饰器?

在不改变原函数代码的情况下,给原函数增加了一些额外的功能,并且能够通用于其他函数,这样的函数就称作为装饰器。

装饰器的调用

可以通过传统调用函数的方式进行调用,也可以通过@装饰器的方式调用

装饰器的特点

  • 通过装饰器,可以在不修改原来函数的情况下对函数进行扩展
  • 一个函数可以同时指定多个装饰器

Atas ialah kandungan terperinci Penghias Python - penghias penutup dan fungsi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:51cto.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam