Làm thế nào để xác định lớp getitem để xử lý cả chỉ mục đơn giản và cắt?
Các đối tượng Slice được tạo tự động khi bạn sử dụng dấu hai chấm trong ký hiệu chỉ số con - và đó là những gì được chuyển tới __getitem__
. Sử dụng isinstance
để kiểm tra xem bạn có đối tượng lát cắt không:
from __future__ import print_function
class Sliceable(object):
def __getitem__(self, subscript):
if isinstance(subscript, slice):
# do your handling for a slice object:
print(subscript.start, subscript.stop, subscript.step)
else:
# Do your handling for a plain index
print(subscript)
Giả sử chúng tôi đang sử dụng một đối tượng phạm vi, nhưng chúng tôi muốn các lát cắt trả về danh sách thay vì các đối tượng phạm vi mới (như nó hiện có):
>>> range(1,100, 4)[::-1]
range(97, -3, -4)
Chúng tôi không thể phân cấp phạm vi vì các giới hạn nội bộ, nhưng chúng tôi có thể ủy quyền cho nó:
class Range:
"""like builtin range, but when sliced gives a list"""
__slots__ = "_range"
def __init__(self, *args):
self._range = range(*args) # takes no keyword arguments.
def __getattr__(self, name):
return getattr(self._range, name)
def __getitem__(self, subscript):
result = self._range.__getitem__(subscript)
if isinstance(subscript, slice):
return list(result)
else:
return result
r = Range(100)
Chúng tôi không có đối tượng Phạm vi có thể thay thế hoàn hảo, nhưng nó khá gần:
>>> r[1:3]
[1, 2]
>>> r[1]
1
>>> 2 in r
True
>>> r.count(3)
1
Để hiểu rõ hơn về ký hiệu lát cắt, đây là ví dụ về cách sử dụng Sliceable:
>>> 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, hãy 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 con một số kiểu nội trang.
Từ tài liệu mô hình dữ liệu :
object.__getslice__(self, i, j)
Không được dùng nữa kể từ phiên bản 2.0: Hỗ trợ các đối tượng lát cắt làm tham số cho __getitem__()
phương thức. (Tuy nhiên, các kiểu tích hợp sẵn trong CPython hiện vẫn được triển khai __getslice__()
. Do đó, bạn phải ghi đè nó trong các lớp dẫn xuất khi triển khai quá trình cắt.)
Điều này đã biến mất trong Python 3.
__getslice__
cho phiên bản python 2.X. thấy docs.python.org/2/reference/datamodel.html#object.__getslice__