# 1. Decorator Lọc: Nhận list tuples, trả về list tuples đã lọc
from unicodedata import name
def filter_amount(threshold):
def decorator(func):
def wrapper(data_list):
# Đảm bảo data_list là list trước khi xử lý
filtered = [item for item in data_list if item[1] >= threshold]
return func(filtered)
return wrapper
return decorator
# 2. Decorator Tính tổng: Nhận list tuples, trả về list tuples đã gom nhóm
def calculate_per_person(func):
def wrapper(data_list):
totals = {}
for name, amount in data_list:
# Sửa lỗi ở đây: Đảm bảo amount là int/float
amount_val = int(amount)
if name in totals:
totals[name] += amount_val
else:
totals[name] = amount_val
# CHÚ Ý: Chuyển dict thành list các tuple để decorator tiếp theo có thể lặp lại
result_as_list = list(totals.items())
return func(result_as_list)
return wrapper
# 3. Decorator Sắp xếp: Nhận list, trả về list
def sort_results(func):
def wrapper(data_list):
# data_list lúc này là [(name, total), ...]
data_list.sort(key=lambda x: (-x[1], x[0]))
return func(data_list)
return wrapper
@filter_amount(10)
@calculate_per_person
@sort_results
def solve(final_list):
for name, total in final_list:
print(f"{name} {total}")
def my_generator():
yield "Hello"
print ("This will be printed after yielding Hello")
yield "World"
func = my_generator()
print(next(func)) # Output: Hello
print(next(func)) # Output: World
# --- Test ---
# if __name__ == "__main__":
# data = [("An", 50), ("Binh", 100), ("An", 20)]
# solve(data)
IyAxLiBEZWNvcmF0b3IgTOG7jWM6IE5o4bqtbiBsaXN0IHR1cGxlcywgdHLhuqMgduG7gSBsaXN0IHR1cGxlcyDEkcOjIGzhu41jCmZyb20gdW5pY29kZWRhdGEgaW1wb3J0IG5hbWUKCmRlZiBmaWx0ZXJfYW1vdW50KHRocmVzaG9sZCk6CglkZWYgZGVjb3JhdG9yKGZ1bmMpOgoJCWRlZiB3cmFwcGVyKGRhdGFfbGlzdCk6CgkJCSMgxJDhuqNtIGLhuqNvIGRhdGFfbGlzdCBsw6AgbGlzdCB0csaw4bubYyBraGkgeOG7rSBsw70KCQkJZmlsdGVyZWQgPSBbaXRlbSBmb3IgaXRlbSBpbiBkYXRhX2xpc3QgaWYgaXRlbVsxXSA+PSB0aHJlc2hvbGRdCgkJCXJldHVybiBmdW5jKGZpbHRlcmVkKQoJCXJldHVybiB3cmFwcGVyCglyZXR1cm4gZGVjb3JhdG9yCgojIDIuIERlY29yYXRvciBUw61uaCB04buVbmc6IE5o4bqtbiBsaXN0IHR1cGxlcywgdHLhuqMgduG7gSBsaXN0IHR1cGxlcyDEkcOjIGdvbSBuaMOzbQpkZWYgY2FsY3VsYXRlX3Blcl9wZXJzb24oZnVuYyk6CglkZWYgd3JhcHBlcihkYXRhX2xpc3QpOgoJCXRvdGFscyA9IHt9CgkJZm9yIG5hbWUsIGFtb3VudCBpbiBkYXRhX2xpc3Q6CgkJCSMgU+G7rWEgbOG7l2kg4bufIMSRw6J5OiDEkOG6o20gYuG6o28gYW1vdW50IGzDoCBpbnQvZmxvYXQKCQkJYW1vdW50X3ZhbCA9IGludChhbW91bnQpIAoJCQlpZiBuYW1lIGluIHRvdGFsczoKCQkJCXRvdGFsc1tuYW1lXSArPSBhbW91bnRfdmFsCgkJCWVsc2U6CgkJCQl0b3RhbHNbbmFtZV0gPSBhbW91bnRfdmFsCgkJCgkJIyBDSMOaIMOdOiBDaHV54buDbiBkaWN0IHRow6BuaCBsaXN0IGPDoWMgdHVwbGUgxJHhu4MgZGVjb3JhdG9yIHRp4bq/cCB0aGVvIGPDsyB0aOG7gyBs4bq3cCBs4bqhaQoJCXJlc3VsdF9hc19saXN0ID0gbGlzdCh0b3RhbHMuaXRlbXMoKSkgCgkJcmV0dXJuIGZ1bmMocmVzdWx0X2FzX2xpc3QpCglyZXR1cm4gd3JhcHBlcgoKIyAzLiBEZWNvcmF0b3IgU+G6r3AgeOG6v3A6IE5o4bqtbiBsaXN0LCB0cuG6oyB24buBIGxpc3QKZGVmIHNvcnRfcmVzdWx0cyhmdW5jKToKCWRlZiB3cmFwcGVyKGRhdGFfbGlzdCk6CgkJIyBkYXRhX2xpc3QgbMO6YyBuw6B5IGzDoCBbKG5hbWUsIHRvdGFsKSwgLi4uXQoJCWRhdGFfbGlzdC5zb3J0KGtleT1sYW1iZGEgeDogKC14WzFdLCB4WzBdKSkKCQlyZXR1cm4gZnVuYyhkYXRhX2xpc3QpCglyZXR1cm4gd3JhcHBlcgoKQGZpbHRlcl9hbW91bnQoMTApCkBjYWxjdWxhdGVfcGVyX3BlcnNvbgpAc29ydF9yZXN1bHRzCmRlZiBzb2x2ZShmaW5hbF9saXN0KToKCWZvciBuYW1lLCB0b3RhbCBpbiBmaW5hbF9saXN0OgoJCXByaW50KGYie25hbWV9IHt0b3RhbH0iKQoJCQpkZWYgbXlfZ2VuZXJhdG9yKCk6Cgl5aWVsZCAiSGVsbG8iCglwcmludCAoIlRoaXMgd2lsbCBiZSBwcmludGVkIGFmdGVyIHlpZWxkaW5nIEhlbGxvIikKCXlpZWxkICJXb3JsZCIKCmZ1bmMgPSBteV9nZW5lcmF0b3IoKQpwcmludChuZXh0KGZ1bmMpKSAgIyBPdXRwdXQ6IEhlbGxvCnByaW50KG5leHQoZnVuYykpICAjIE91dHB1dDogV29ybGQKCiMgLS0tIFRlc3QgLS0tCiMgaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKIyAgICAgZGF0YSA9IFsoIkFuIiwgNTApLCAoIkJpbmgiLCAxMDApLCAoIkFuIiwgMjApXQojICAgICBzb2x2ZShkYXRhKQ==