def make_bold(fn):
return lambda : "<b>" + fn() + "</b>"
def make_italic(fn):
return lambda : "<i>" + fn() + "</i>"
@make_bold
@make_italic
def hello():
return "hello world"
helloHTML = hello()
Keluaran: "<b><i>hello world</i></b>"
Saya kira-kira mengerti tentang dekorator dan cara kerjanya dengan salah satunya di sebagian besar contoh.
Dalam contoh ini, ada 2 di antaranya. Dari output, sepertinya yang @make_italic
dieksekusi dulu, baru @make_bold
.
Apakah ini berarti bahwa untuk fungsi dekorasi, ini akan menjalankan fungsi terlebih dahulu kemudian bergerak ke atas untuk dekorator lain? Seperti @make_italic
dulu @make_bold
, lalu sebaliknya.
Jadi ini berarti bahwa ini berbeda dari norma pendekatan top-down di kebanyakan bahasa pemrograman? Hanya untuk kasus dekorator ini? Atau apakah saya salah?
python
decorator
python-decorators
Pemula
sumber
sumber
a(b(x))
top-down (jika Anda membayangkan itu terbagi menjadi 3 baris)Jawaban:
Dekorator membungkus fungsi yang mereka dekorasi. Begitu
make_bold
menghiasi hasilmake_italic
dekorator yang menghiasihello
fungsinya.The
@decorator
sintaks gula benar-benar hanya sintaksis; pengikut:@decorator def decorated_function(): # ...
benar-benar dijalankan sebagai:
def decorated_function(): # ... decorated_function = decorator(decorated_function)
mengganti
decorated_function
objek asli dengan apa pun yangdecorator()
dikembalikan.Dekorator bertumpuk mengulangi proses itu ke luar .
Jadi sampel Anda:
@make_bold @make_italic def hello(): return "hello world"
dapat diperluas menjadi:
def hello(): return "hello world" hello = make_bold(make_italic(hello))
Saat Anda menelepon
hello()
sekarang, Anda memanggil objek yang dikembalikan olehmake_bold()
, sungguh.make_bold()
mengembalikan alambda
yang memanggil fungsimake_bold
dibungkus, yang merupakan nilai kembalianmake_italic()
, yang juga merupakan lambda yang memanggil aslinyahello()
. Memperluas semua panggilan ini yang Anda dapatkan:hello() = lambda : "<b>" + fn() + "</b>" # where fn() -> lambda : "<i>" + fn() + "</i>" # where fn() -> return "hello world"
sehingga outputnya menjadi:
"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"
sumber
@make_bold #make_bold = make_bold(hello)
@make_italic #make_italic = make_italic (hello)
? Saya tidak yakin jika berdasarkan ini, itu akan membungkus hasil pertama. Atau untuk kasus 2 pembungkus ini, IDE akan menggunakanmake_bold(make_italic(hello))
seperti yang Anda sebutkan, bukan yang saya bagikan?make_bold()
membungkus outputmake_italic()
, yang digunakan untuk membungkushello
, jadi setara denganmake_bold(make_italic(hello))
.def inner: return "<b>" + fn() + "</b>"
, makareturn inner
akan menjadi versi fungsi 'biasa'; bukan perbedaan yang besar.make_italic
dekorator dijalankan sebelummake_bold
dekorator , karenamake_italic
paling dekat dengandef
. Namun, saya lupa bahwa urutan eksekusi kode yang didekorasi : yangmake_bold
didekorasi (yaitu lambda tebal) dijalankan terlebih dahulu, diikuti oleh lambda yangmake_italic
didekorasi (yaitu lambda miring).