
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()
và 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:
Nội dung chính
Bạn Đang Xem: Hướng dẫn dùng get item python
- Python: Triển khai cắt trong __getitem__?
- Làm thế nào để xác định lớp getitem để xử lý cả chỉ mục đơn giản và cắt?
- Python 2, lưu ý:
- Đăng nhập để trả lời câu hỏi
- Có thể bạn quan tâm
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 dict
tối ưu hóa lớp tích hợp (tôi không muốn kế thừa dạng UserDict
hoặ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ẻ
Xem Tắt
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 getitem
phươ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
Xem Thêm : Tổng hợp 6 điều kiện tạo ra hồ quang điện hot nhất
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
, stop
và step
cá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 < 0 : #Handle negative indices
key += len( self )
if key < 0 or key >= len( self ) :
raise IndexError, "The index (%d) is out of range."%key
return self.getData(key) #Get the data from elsewhere
else:
raise TypeError, "Invalid argument type."
Các lát cắt không
trả về cùng loại, điều này là không, nhưng nó hoạt động với tôi.
59 hữu ích 2 bình luận chia sẻ
answer
10
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 lát được tự động tạo khi bạn sử dụng dấu hai chấm trong ký hiệu đăng ký – và đó là những gì được truyền vào __getitem__
. Sử dụng isinstance
để kiểm tra nếu bạn có một đối tượng lát:
from __future__ import print_function
class Sliceable(object):
def __getitem__(self, given):
if isinstance(given, slice):
# do your handling for a slice object:
print(given.start, given.stop, given.step)
else:
# Do your handling for a plain index
print(given)
Ví dụ sử dụng:
>>> 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 :
Xem Thêm : 7 hinh anh binh luan facebook hai huoc hay nhất hiện nay
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 given
có 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
Nguồn: https://quatangtiny.com
Danh mục: Blog