Hướng dẫn __getitem__ python

Tôi sử dụng python3.7 và đối với một số ứng dụng, hãy tạo một lớp kế thừa từ a dict, nhưng gặp sự cố khi triển khai items[]values[]các phương pháp để làm cho nó hoạt động chính xác. Lớp này ghi đè nhiều phương thức, nhưng ở đây tôi đã đặt một ví dụ rất đơn giản chỉ để minh họa vấn đề chính xác:

class MyFunction:
    def __call__[self]:
        return 5

class MyDict[dict]:
    def __getitem__[self, key]:
        item = super[].__getitem__[key]
        if isinstance[item, MyFunction]:
            return item[]
        else:
            return item

    def get[self, key, default=None]:
        if self.__contains__[key]:
            return self.__getitem__[key]
        if isinstance[default, MyFunction]:
            return default[]
        return default

    # def __copy__[self]:
    #     return type[self][self]
    # 
    # def copy[self]:
    #     return self.__copy__[]

    # def __iter__[self]:
    #     return super[].__iter__[]


d = MyDict[a=MyFunction[], b=3]

Tôi muốn hơn là tôi nhận được một giá trị theo các trường hợp chính của MyFunctionđược gọi. Điều này hoạt động tốt:

for k in d:
    print[k, d[k]]

và in ra kết quả mong đợi:

a 5
b 3

Nhưng hai điều này không:

for v in d.values[]:
    print[v]

for k, v in d.items[]:
    print[k, v]

Họ in repr của hàm.

Làm cách nào tôi có thể gọi cho họ __getitem__?

Lưu ý : Nó có thể là một số loại dicttối ưu hóa lớp tích hợp [tôi không muốn kế thừa dạng UserDicthoặc Mapping]. Ví dụ nếu tôi bỏ ghi chú:

def  __iter__[self]:
     return super[].__iter__[]

Các cuộc gọi:

new_d = d.copy[]
new_d = dict[d]
new_d = dict[**d]

sẽ gọi __getitem__

4 hữu ích 4 bình luận 1.1k xem chia sẻ

Python: Triển khai cắt trong __getitem__?

Tôi đang cố gắng thực hiện chức năng cắt lát cho một lớp tôi đang tạo để tạo ra một biểu diễn vector.

Tôi có mã này cho đến nay, mà tôi tin rằng sẽ thực hiện đúng lát cắt nhưng bất cứ khi nào tôi thực hiện một cuộc gọi như v[4]v là một python vector trả về lỗi về việc không có đủ tham số. Vì vậy, tôi đang cố gắng tìm ra cách xác định getitemphương thức đặc biệt trong lớp để xử lý cả chỉ mục đơn giản và cắt.

def __getitem__[self, start, stop, step]:
    index = start
    if stop == None:
        end = start + 1
    else:
        end = stop
    if step == None:
        stride = 1
    else:
        stride = step
    return self.__data[index:end:stride]

  • python
  • slice
  • python-datamodel

88 hữu ích 0 bình luận 50k xem chia sẻ

answer

102

Các __getitem__[]phương pháp sẽ nhận được một sliceđối tượng khi đối tượng được thái lát. Đơn giản chỉ cần nhìn vào start, stopstepcác thành viên của sliceđối tượng để có được các thành phần cho một slice.

>>> class C[object]:
...   def __getitem__[self, val]:
...     print val
... 
>>> c = C[]
>>> c[3]
3
>>> c[3:4]
slice[3, 4, None]
>>> c[3:4:-2]
slice[3, 4, -2]
>>> c[[]:1j:'a']
slice[[], 1j, 'a']

102 hữu ích 5 bình luận chia sẻ

answer

59

Tôi có một danh sách "tổng hợp" [một danh sách mà dữ liệu lớn hơn bạn muốn tạo trong bộ nhớ] và tôi __getitem__trông như thế này:

def __getitem__[ self, key ] :
    if isinstance[ key, slice ] :
        #Get the start, stop, and step from the slice
        return [self[ii] for ii in xrange[*key.indices[len[self]]]]
    elif isinstance[ key, int ] :
        if key >> sliceme = Sliceable[]
>>> sliceme[1]
1
>>> sliceme[2]
2
>>> sliceme[:]
None None None
>>> sliceme[1:]
1 None None
>>> sliceme[1:2]
1 2 None
>>> sliceme[1:2:3]
1 2 3
>>> sliceme[:2:3]
None 2 3
>>> sliceme[::3]
None None 3
>>> sliceme[::]
None None None
>>> sliceme[:]
None None None

Python 2, lưu ý:

Trong Python 2, có một phương thức không dùng nữa mà bạn có thể cần ghi đè khi phân lớp một số loại dựng sẵn.

Từ tài liệu datamodel :

object.__getslice__[self, i, j]

Không dùng nữa kể từ phiên bản 2.0: Hỗ trợ các đối tượng lát làm tham số cho __getitem__[]phương thức. [Tuy nhiên, các loại tích hợp trong CPython hiện vẫn đang triển khai __getslice__[]. Do đó, bạn phải ghi đè nó trong các lớp dẫn xuất khi triển khai cắt.]

Điều này đã biến mất trong Python 3.

10 hữu ích 1 bình luận chia sẻ

answer

7

7 hữu ích 0 bình luận chia sẻ

answer

6

Để mở rộng câu trả lời của Aaron, đối với những thứ như numpy, bạn có thể thực hiện cắt đa chiều bằng cách kiểm tra xem liệu givencó phải là tuple:

class Sliceable[object]:
    def __getitem__[self, given]:
        if isinstance[given, slice]:
            # do your handling for a slice object:
            print["slice", given.start, given.stop, given.step]
        elif isinstance[given, tuple]:
            print["multidim", given]
        else:
            # Do your handling for a plain index
            print["plain", given]

sliceme = Sliceable[]
sliceme[1]
sliceme[::]
sliceme[1:, ::2]

`` `

Đầu ra:

['plain', 1]
['slice', None, None, None]
['multidim', [slice[1, None, None], slice[None, None, 2]]]

6 hữu ích 1 bình luận chia sẻ

Đăng nhập để trả lời câu hỏi

Có thể bạn quan tâm

Chủ Đề