Nói chung, nếu bạn cần phải duy trì trạng thái giữa một cuộc gọi đến một hàm và tiếp theo, những gì bạn muốn là một trong hai một đối tượng (của bạn giải pháp) hoặc máy phát điện. Trong một số trường hợp, một cái sẽ đơn giản hơn cái kia, nhưng không có gì là sai với cách bạn đã thực hiện nó, về nguyên tắc (mặc dù bạn dường như có một số vấn đề với việc triển khai).
Đề xuất của Sven, itertools.count()
, là máy phát điện. thực hiện của nó là một cái gì đó như thế này:
def count():
i = 0
while True:
yield i
i += 1
Bây giờ, nếu bạn muốn nó được callable như một chức năng, thay vì phải làm next(c)
, bạn có thể định nghĩa một wrapper mà làm cho nó như vậy:
def count(c=itertools.count()):
return next(c)
Hoặc một dòng không thể tránh khỏi lambda:
count = lambda c=itertools.count(): next(c)
sau đó count()
trả về số nguyên tiếp theo mỗi lần bạn gọi nó.
Tất nhiên, nếu bạn muốn để có thể tạo ra bất kỳ số chức năng có thể được gọi, đều có truy cập của riêng mình, bạn có thể viết một nhà máy cho rằng:
def counter():
return lambda c=itertools.count(): next(c)
Sau đó, nó là:
c = counter()
print c() # 0
print c() # 1
# etc
Điều này dường như vẫn đơn giản đối với tôi hơn là một đối tượng, nhưng không nhiều. Nếu trạng thái hoặc logic của bạn phức tạp hơn, việc đóng gói của đối tượng có thể thắng.
Bạn có chắc là mã của bạn đang hoạt động không? Phương thức '__get __()' chỉ được gọi khi lấy một thuộc tính từ một lớp kiểu mới, mà dường như không xảy ra ở đây. –
Đúng, nó hoạt động tốt. Bạn có nghĩa là nó chỉ nên làm việc nếu tôi: 'number = new Incrementer()'? Tại sao vậy? –
[Tôi nghi ngờ mã của bạn in '0 1 2'] (http://ideone.com/kvCE1). Và tôi không nói về 'number = new Incrementer()' - bạn có vẻ khó hiểu ở đây, không có toán tử 'new' nào trong Python. Tôi đang nói về việc gọi [descriptors] (http://docs.python.org/reference/datamodel.html#descriptors). –