__Getitem__ এ স্লাইসিং কার্যকর করছে


112

আমি তৈরি করছি এমন শ্রেণীর জন্য স্লাইস কার্যকারিতা বাস্তবায়নের চেষ্টা করছি যা ভেক্টরের উপস্থাপনা তৈরি করে।

আমার এখনও অবধি এই কোডটি রয়েছে, যা আমি বিশ্বাস করি যে এই স্লাইসটি সঠিকভাবে প্রয়োগ করা হবে তবে যখনই আমি v[4]ভি কল একটি ভেক্টর পাইথন এর মতো একটি কল করলে পর্যাপ্ত পরামিতি না থাকার বিষয়ে ত্রুটি ফিরে আসে। সুতরাং আমি কীভাবে getitemক্লাস ইনডেক্স এবং স্লাইসিং উভয় পরিচালনা করতে আমার ক্লাসে বিশেষ পদ্ধতিটি সংজ্ঞায়িত করব তা বোঝার চেষ্টা করছি ।

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]

উত্তর:


118

__getitem__()পদ্ধতি পাবেন sliceযখন বস্তুর টুকরা করা হয় অবজেক্ট। কেবলমাত্র তাকান start, stopএবং stepসদস্যদের 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')

10
দ্রষ্টব্য: অন্তর্নির্মিত ধরণের তালিকা বা টিপলের মতো বাড়ানোর __getslice__জন্য আপনাকে পাইথন ২ এক্স এক্স সংস্করণে প্রয়োগ করতে হবে । দেখতে docs.python.org/2/reference/datamodel.html#object.__getslice__
gregorySalvan

@ গ্রেগরিসালভান: সেই বিভাগের নীচে সেই সামঞ্জস্যতার উদাহরণটি কি কেবল পুনরাবৃত্তি করে না?
এরিক

3
@ এরিক: না, কারণ দ্বিতীয় কোলনের উপস্থিতি বাইপাস করে __get/set/delslice__। যদিও এটি বেশ সূক্ষ্ম।
ব্যবহারকারী 2357112 25:47

@ ইউজার 2357112: বাহ, সম্পূর্ণরূপে সেই দ্বিতীয় কোলন মিস হয়েছে - ধন্যবাদ!
এরিক

অ্যালাঙ্কালভিটি আইআইআরসি, এটি পাইথন ২ এ নতুন ধরণের ক্লাস তৈরি করার জন্য
wjandrea

64

আমার একটি "সিন্থেটিক" তালিকা রয়েছে (একটি যেখানে আপনি মেমরিতে তৈরি করতে চান তার চেয়ে বড় ডেটা) এবং আমার __getitem__চেহারাটি এর মতো:

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."

স্লাইস একই ধরণের ফিরবে না, যা একটি নো, তবে এটি আমার পক্ষে কাজ করে।


1
কী <= বা কী> = লেন (স্ব) থাকলে কী> = লেন (স্ব) হওয়া উচিত নয়? একটি কী <-len (স্ব) উত্তীর্ণ হলে কী হবে?
ইস্তান

20

প্লেইন ইনডেক্স এবং স্লাইসিং উভয়ই হ্যান্ডেল করার জন্য গেটাইটেম ক্লাসটি কীভাবে সংজ্ঞায়িত করবেন?

স্লাইস বস্তু স্বয়ংক্রিয়ভাবে যখন আপনি সাবস্ক্রিপ্ট স্বরলিপি একটি কোলন ব্যবহার করে নির্মিত পরার - এবং যে কি প্রেরণ করা হয় __getitem__। আপনার isinstanceযদি টুকরো টুকরো বস্তু রয়েছে তা পরীক্ষা করতে ব্যবহার করুন :

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)

বলুন আমরা একটি ব্যাপ্তি অবজেক্ট ব্যবহার করছিলাম, তবে আমরা নতুন রেঞ্জের অবজেক্টগুলির পরিবর্তে টুকরোগুলি তালিকা ফিরিয়ে দিতে চাই (যেমন এটি হয়):

>>> range(1,100, 4)[::-1]
range(97, -3, -4)

অভ্যন্তরীণ সীমাবদ্ধতার কারণে আমরা সাবক্লাসের পরিসরটি পারি না, তবে আমরা এতে প্রতিনিধি করতে পারি:

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)

আমাদের কাছে পুরোপুরি প্রতিস্থাপনযোগ্য ব্যাপ্তি অবজেক্ট নেই তবে এটি মোটামুটি কাছাকাছি:

>>> r[1:3]
[1, 2]
>>> r[1]
1
>>> 2 in r
True
>>> r.count(3)
1

স্লাইস সংকেতটি আরও ভালভাবে বুঝতে, স্লাইসিয়েবলের উদাহরণ ব্যবহারের জন্য:

>>> 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

পাইথন 2, সচেতন থাকুন:

পাইথন 2 এ, একটি অবহিত পদ্ধতি রয়েছে যা কিছু বিল্টিন প্রকারের সাবক্লাসিং করার সময় আপনার ওভাররাইডের প্রয়োজন হতে পারে।

থেকে datamodel ডকুমেন্টেশন :

object.__getslice__(self, i, j)

সংস্করণ ২.০ থেকে অবহেলিত:__getitem__() পদ্ধতির পরামিতি হিসাবে স্লাইস অবজেক্টগুলিকে সমর্থন করে । (তবে সিপিথনের অন্তর্নির্মিত প্রকারগুলি বর্তমানে কার্যকর করে __getslice__()Therefore

এটি পাইথন 3 এ চলে গেছে।


7

হারুনের উত্তরটি প্রসারিত করতে, এই জাতীয় জিনিসের জন্য numpy, আপনি givenএকটি কিনা তা পরীক্ষা করে বহু-মাত্রিক স্লাইসিং করতে পারেন 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]

``

আউটপুট:

('plain', 1)
('slice', None, None, None)
('multidim', (slice(1, None, None), slice(None, None, 2)))

একটি ছোটখাট ফলো-আপ হিসাবে, এখানে একটি উদাহরণ এই নিযুক্ত একটি সঙ্গে ম্যাটল্যাব ইন্ডেক্স এবং NumPy ইন্ডেক্স (যা বর্তমানে ম্যাটল্যাব R2016b সমর্থিত নয়) মধ্যে ম্যাপ, এর উদাহরণ ব্যবহার এটি।
এরিক কাজিনো

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.