Mọi người giúp mình dịch câu này với
Nhờ mọi người dịch giúp 1 câu về decorator Python
Không đồng tình lắm, function vẫn là function, không thể đổi hành vi của function cụ thể nào đó mà không đổi code được.
Decorating là lấy function gốc làm nguyên liệu, thêm mắm muối để chế ra function mới, còn cái function cũ vẫn ở đó chứ chẳng đi đâu cả.
Cái implementation của function cũ đúng là nó vẫn không thay đổi gì cả nhưng thứ mà code khác có thể access được lại là decorator function. Nó thế chỗ cho function cũ thì chả phải làm thay đổi hành vi. Decorator trong Python hoàn toàn có thể làm vô hiệu hóa implementation của một Function luôn. Switch implementation của 2 Function với nhau cũng được
Dùng @
chỉ là bind cái name của function cũ vào function mới, dùng name khác bind cũng được, nên có thể decorating 1 hàm theo nhiều cách độc lập nhau. Còn cái funtion gốc vẫn ở đó trong bộ nhớ, hành vi không hề thay đổi. Cái ta sử dụng là hàm hoàn toàn mới. Dùng @
chỉ là 1 cách viết cho tiện, decorating bản chất vẫn là sử dụng call back mechanism
Decorator sao lại liên quan tới callback vậy?
Bởi vì hàm gốc được pass vào hàm decorate như một tham số tại running time.
Cái này không chính xác, bản chất của decorator chính là thay đổi hành vi của hàm.
Vậy tất cả những tham số được đưa vào 1 hàm khác mà cũng là hàm thì được gọi là callback à? Nếu hàm được decorated mà thực thi trước hàm gốc thì có được gọi là callforward không? Decorator trong Python phức tạp và khó nhằn hơn chỉ là “callback” không thôi.
Hai hàm gốc làm ví dụ:
def origin(name = ""):
return "Mr."+name
#thêm hàm nữa, nhưng chưa cần dùng vội
def female_origin(name=""):
return "Ms." + name
Định nghĩa 2 hàm decorate làm ví dụ:
def first_decorate(func):
def wrapper(name):
return func(name)+" and first decorate"
return wrapper
def second_decorate(func):
def wrapper(name):
return func(name)+ " and second decorate"
return wrapper
Nguyên thủy của decorating chính là bỏ hàm origin
vào làm tham số, sản suất ra hàm wrapper
, gán cho nó cái tên alter
alter_1 = first_decorate(origin)
Origin vẫn nằm ở đó, hành vi không đổi:
print(origin("John"))
print(alter_1("John"))
output:
Mr.John
Mr.John and first decorate
Lúc call alter_1 = first_decorate(origin)
là chương trình làm gì? nó nhận origin
làm tham số đầu vào, đó chính là call back mechanic, khi bạn có thể chọn hàm một cách linh động ở run time, không có gì cao siêu hơn cả.
Thậm chí cho user được chọn hàm để đưa vào first_decorate
:
i = int(input("Moi chon ham [1]/[2]: "))
ham = origin if i == 1 else female_origin
alter_1 = first_decorate(ham)
print(alter_1("John"))
Moi chon ham [1]/[2]: 2
Ms.John and first decorate
“Lắp” origin
vào nhiều kiểu decorate
khác nhau:
alter_1 = first_decorate(origin)
alter_2 = second_decorate(origin)
alter_1_2 = second_decorate(first_decorate(origin))
print(origin("John"))
print(alter_1("John"))
print(alter_2("John"))
print(alter_1_2("John"))
output:
Mr.John
Mr.John and first decorate
Mr.John and second decorate
Mr.John and first decorate and second decorate
Dùng @
là bạn làm gì:
@first_decorate
def female_origin(name=""):
return "Ms." + name
là bạn viết tắt của cái việc female_origin = first_decorate(female_origin)
, là bạn unbind cái name female_origin
ra khỏi hàm cũ, và bind nó vào hàm mới (hàm wrapper
).
Đây chỉ là 1 syntax, 1 cách viết gọn của python, không hơn. Và cái hàm origin cũ vẫn nằm trong bộ nhớ chứ không hề đi đâu cả, cái thuật ngữ “decorate” bạn có thể hiểu trong bối cảnh của python là dùng @
, nhưng theo mình bản chất của nó là nhận vào 1 hàm và trả về 1 hàm mới dựa vào hàm cho trước, đó chính xác là 1 ứng dụng của callback.
In short: Ngay từ dòng này: def first_decorate(func)
mình xin khẳng định luôn: đây là callback.
My thought:
A decorator is a function that takes one or multiple functions as arguments to produce a function which tends to have the behavior of the original functions plus additional behaviors.
Nó gần với từ “decorate”(trang trí) hơn là “change” hay “modify” (thay đổi).
Một ý nữa, hàm sau khi decorate mà thay đổi nhiều tới mức gốc trả về string
nhưng sau khi decorated lại trả về int
, hay hàm gốc làm phép tính cộng nhưng hàm decorated lại dùng phép cộng đó để nhân ma trận, thì không biết còn đúng trong cái bối cảnh của thuật ngữ “decorator” không? Cái này phụ thuộc ý kiến của từng người? Mình không thấy có formal definition nào về thuật ngữ này.
Nếu Python decorator chỉ dừng lại ở việc như bạn ví dụ thì có lẽ số phận của Python cũng tương tự lolcode rồi. Thực tế thì decorator trong Python phức tạp là do tính lỏng lẻo của ngôn ngữ này, ở đó mọi thứ đều là object và có thể thay đổi được.
Vài ví dụ về decorator thay đổi “behavior” của function/method/class mà m nhớ ra tại thời điểm này:
-
decorator function is in the spotlight, another example
…
Sorry, my bad, you’re right! It’s indeed a callback implementation.