Có hai cách để thực hiện. Cách hướng đối tượng là làm cho một lớp:
class max_execs:
def __init__(self, max_executions):
self.max_executions = max_executions
self.executions = 0
def __call__(self, func):
@wraps(func)
def maybe(*args, **kwargs):
if self.executions < self.max_executions:
self.executions += 1
return func(*args, **kwargs)
else:
print "fail"
return maybe
Xem this question cho một lời giải thích của wraps
.
Tôi thích phương pháp tiếp cận OOP ở trên cho loại trang trí này, vì bạn về cơ bản có một biến số riêng tư theo dõi số lần thực hiện. Tuy nhiên, cách tiếp cận khác là sử dụng đóng cửa, chẳng hạn như
def max_execs(max_executions):
executions = [0]
def actual_decorator(func):
@wraps(func)
def maybe(*args, **kwargs):
if executions[0] < max_executions:
executions[0] += 1
return func(*args, **kwargs)
else:
print "fail"
return maybe
return actual_decorator
Điều này liên quan đến ba chức năng. Hàm max_execs
được đưa ra một tham số cho số lần thực hiện và trả về một trình trang trí sẽ hạn chế bạn đối với nhiều cuộc gọi đó. Hàm đó, actual_decorator
, thực hiện tương tự như phương thức __call__
của chúng tôi trong ví dụ OOP. Sự kỳ quặc duy nhất là vì chúng ta không có một lớp với các biến riêng, chúng ta cần phải biến đổi biến số executions
nằm trong phạm vi bên ngoài của việc đóng cửa của chúng ta. Python 3.0 hỗ trợ điều này với câu lệnh nonlocal
, nhưng trong Python 2.6 hoặc phiên bản cũ hơn, chúng tôi cần thực hiện các lệnh thực thi của chúng tôi trong danh sách để nó có thể bị đột biến.
Nguồn
2009-07-09 20:27:09
khi áp dụng trang trí này, mã "dịch" bằng python như thế nào? Ví dụ, nếu phương pháp của tôi được gọi là blabla, và tôi áp dụng thuộc tính max_execs, Python sẽ thấy nó như thế nào? blabla = max_execs (5) (blabla)? – Geo
Tôi đã cập nhật câu trả lời để bao gồm bản dịch, nhưng bạn có ý tưởng đúng. – mipadi