Nhờ mọi người dịch giúp 1 câu về decorator Python

Mọi người giúp mình dịch câu này với

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ả.

1 Like

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

1 Like

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

2 Likes

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.

2 Likes

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.

2 Likes

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.

2 Likes

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:

  1. property/setter/getter

  2. classmethod/staticmethod

  3. Register API/plugins, resource validation

  4. dataclasses

  5. decorator function is in the spotlight, another example

Thực tế là có đó:
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class.

Sorry, my bad, you’re right! It’s indeed a callback implementation.

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?