Python __getitem__ và trong toán tử dẫn đến hành vi lạ


34

Điều gì giải thích cho hành vi sau:

class Foo:
    def __getitem__(self, item):
        print("?")
        return 1

f = Foo()

1 in f  # prints one ? and returns True

5 in f  # prints ? forever until you raise a Keyboard Exception

# Edit: eventually this fails with OverflowError: iter index too large

Câu trả lời:


45

Nếu một đối tượng không có __contains__triển khai, hãy inquay lại mặc định về cơ bản hoạt động như thế này:

def default__contains__(self, element):
    for thing in self:
        if thing == element:
            return True
    return False

Và nếu một đối tượng không có __iter__triển khai, hãy forquay lại mặc định về cơ bản hoạt động như thế này:

def default__iter__(self):
    i = 0
    try:
        while True:
            yield self[i]
            i += 1
    except IndexError:
        pass

Các giá trị mặc định này được sử dụng ngay cả khi đối tượng không có ý định là một chuỗi.

Của bạn 1 in f5 in fcác bài kiểm tra đang sử dụng các dự phòng mặc định cho infor, dẫn đến hành vi được quan sát. 1 in ftìm thấy 1ngay lập tức, nhưng bạn __getitem__không bao giờ trở lại 5, vì vậy 5 in fchạy mãi mãi.

(Vâng, trên thực tế, tình hình thực hiện tham chiếu của Python, mặc định __iter__cửa hàng dự phòng các chỉ số trong một biến C cấp các loại Py_ssize_t, vì vậy nếu bạn chờ đợi đủ lâu, rằng biến đạt cực đại và Python đặt ra một OverflowError . Nếu bạn thấy rằng, bạn phải có trên bản dựng Python 32 bit. Máy tính chưa tồn tại đủ lâu để bất kỳ ai có thể đánh nó trên Python 64 bit.)


Về OverflowError, tôi đã chạy nó trên cả 64 và 32 bit, và bạn nói đúng, tôi chỉ thấy nó trên 32 bit.
Matthew Moisen

Bạn có tình cờ biết các tài liệu giải thích điều này? Tôi muốn đọc lên lý do tại sao việc thực hiện này đã được quyết định.
Matthew Moisen


4
@MatthewMoisen: Những mặc định này là hành vi ban đầu của forin, trước khi giới thiệu __iter____contains__. Xem tài liệu Python 1.4 tại đâytại đây .
user2357112 hỗ trợ Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.