টুপল স্লাইসিং তালিকার বিপরীতে কোনও নতুন অবজেক্ট ফেরত দেবে না


12

পাইথনে (2 এবং 3)। যখনই আমরা তালিকাটি স্লাইসিং ব্যবহার করি তবে এটি একটি নতুন অবজেক্ট প্রদান করে, যেমন:

l1 = [1,2,3,4]
print(id(l1))
l2 = l1[:]
print(id(l2))

আউটপুট

>>> 140344378384464
>>> 140344378387272

যদি একই জিনিসকে টিপল দিয়ে পুনরাবৃত্তি করা হয়, একই জিনিসটি ফিরে আসে, যেমন:

t1 = (1,2,3,4)
t2 = t1[:]
print(id(t1))
print(id(t2))

আউটপুট

>>> 140344379214896
>>> 140344379214896

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

আমার বোধগম্যতা হ'ল এটি একই পদার্থটি ফিরিয়ে দিচ্ছে যেমন টিউপসগুলি স্থাবর হয় এবং এটির একটি নতুন অনুলিপি তৈরি করার কোনও মানে নেই। কিন্তু আবার, নথিতে এটি কোথাও উল্লেখ করা হয়নি।



l2 = tuple(iter(l1))অপ্টিমাইজেশনকে বাইপাস করে
ক্রিস_আরান্ডস

লক্ষ্য সি-API- এর জন্যPyTuple_GetSlice আপনার প্রশ্নের দেখার পর ভুলভাবে নথিভুক্ত করা হয়। দস্তাবেজগুলি এখন ঠিক করা হয়েছে (এটি ছিল বিপিও ইস্যু 38557 )।
উইম

উত্তর:


13

বাস্তবায়নগুলি অপরিবর্তনীয় প্রকারের জন্য অভিন্ন দৃষ্টান্ত ফিরিয়ে দিতে বিনামূল্যে (সিপিথনে, আপনি মাঝে মাঝে স্ট্রিং এবং পূর্ণসংখ্যার জন্য একই রকম অপটিমাইজেশন দেখতে পাবেন)। যেহেতু অবজেক্টটি পরিবর্তন করা যায় না, তাই ইউজার কোডে এমন কোনও কিছুই নেই যা এটির কোনও অনন্য উদাহরণ রয়েছে বা বিদ্যমান উদাহরণের সাথে অন্য কোনও রেফারেন্স রয়েছে কিনা তা যত্নশীল হওয়া দরকার।

আপনি এখানে সি কোড শর্ট সার্কিট খুঁজে পেতে পারেন ।

static PyObject*
tuplesubscript(PyTupleObject* self, PyObject* item)
{
    ... /* note: irrelevant parts snipped out */
    if (start == 0 && step == 1 &&
                 slicelength == PyTuple_GET_SIZE(self) &&
                 PyTuple_CheckExact(self)) {
            Py_INCREF(self);          /* <--- increase reference count */
            return (PyObject *)self;  /* <--- return another pointer to same */
        }
    ...

এটি একটি বাস্তবায়ন বিশদ, নোট করুন যে পাইপি একই কাজ করে না।


ধন্যবাদ @ উইম এটি এখন বোধগম্য হয়। আমি সি তে অভিজ্ঞ না হওয়ায় কেবল বিষয়টিকে বন্ধ করে দিচ্ছি, a-> ob_item ঠিক কী করে? আমি এটি সন্ধান করার চেষ্টা করেছি। তবে আমি যা বুঝতে পেরেছিলাম তা হ'ল এটি "ক" এর ঠিকানা নেয় এবং "ob_item" কে এগিয়ে নিয়ে যায়। আমার বোধগম্যতা ছিল ob_item এর মধ্যে স্টোরেজ ঠিকানা সংখ্যা রয়েছে যা "1" আইটেম তৈরি করে। # অফ দ্য টপিক
বিজয়

2
এটি এখানে টিপলের জন্য টাইপিডেফটি দেখতে সহায়তা করতে পারে । তাই a->ob_itemভালো হয় (*a).ob_item, অর্থাত্ এটা সদস্য নামক পায় ob_itemথেকে PyTupleObjectএকটি প্রতি নির্দেশ করা হয়, এবং + ilow তারপর ফালি শুরুতে এগিয়ে।
wim

3

এটি বাস্তবায়নের বিশদ। কারণ তালিকাগুলি পরিবর্তনীয়, l1[:] অবশ্যই একটি অনুলিপি তৈরি করতে হবে, কারণ আপনি পরিবর্তনগুলি l2প্রভাবিত হওয়ার প্রত্যাশা করবেন না l1

যেহেতু একটি টিউপল অপরিবর্তনীয় , যদিও এর কোনও কিছুই আপনার দৃশ্যমান উপায়ে t2প্রভাবিত করতে পারে t1না, তাই সংকলকটি বিনামূল্যে এবং (তবে প্রয়োজনীয় নয় ) একই অবজেক্টের জন্য t1এবং ব্যবহার করতে পারে t1[:]


1

পাইথনে ৩। * my_list[:]সিন্টেক্সটিক চিনি type(my_list).__getitem__(mylist, slice_object)যেখানে: slice_objectএটির my_listবৈশিষ্ট্য (দৈর্ঘ্য) এবং এক্সপ্রেশন থেকে তৈরি একটি স্লাইস অবজেক্ট [:]। অবজেক্টস যে এইরকম আচরণ পাইথন ডেটা মডেল subscriptable বলা হয় দেখতে এখানে । তালিকাগুলি এবং tuples __getitem__জন্য একটি অন্তর্নির্মিত পদ্ধতি।

সিপিথনে, এবং তালিকাগুলি এবং তালিকার জন্য, __getitem__বাইটকোড অপারেশন দ্বারা ব্যাখ্যা করা হয় BINARY_SUBSCRযা এখানে টিপলস এবং এখানে তালিকার জন্য প্রয়োগ করা হয়

টিউপলসের ক্ষেত্রে, কোডটি দিয়ে হেঁটে আপনি দেখতে পাবেন যে এই কোড ব্লকটিতে , কোনও আইটেম টাইপ করা থাকলে এবং স্লাইসটি পুরো টিপলটিতে মূল্যায়ন করে যদি এই কোড ব্লকে , static PyObject* tuplesubscript(PyTupleObject* self, PyObject* item)এটি একইভাবে একটি রেফারেন্স ফিরিয়ে দেয় ।PyTupleObjectPySlice

    static PyObject*
    tuplesubscript(PyTupleObject* self, PyObject* item)
    {
        /* checks if item is an index */ 
        if (PyIndex_Check(item)) { 
            ...
        }
        /* else it is a slice */ 
        else if (PySlice_Check(item)) { 
            ...
        /* unpacks the slice into start, stop and step */ 
        if (PySlice_Unpack(item, &start, &stop, &step) < 0) { 
            return NULL;
        }
       ...
        }
        /* if we start at 0, step by 1 and end by the end of the tuple then !! look down */
        else if (start == 0 && step == 1 &&
                 slicelength == PyTuple_GET_SIZE(self) && 
                 PyTuple_CheckExact(self)) {
            Py_INCREF(self); /* increase the reference count for the tuple */
            return (PyObject *)self; /* and return a reference to the same tuple. */
        ...
}

এখন আপনি কোডটি পরীক্ষা করে static PyObject * list_subscript(PyListObject* self, PyObject* item)দেখুন এবং নিজেরাই দেখুন যে স্লাইস যাই হোক না কেন, একটি নতুন তালিকা অবজেক্ট সর্বদা ফিরে আসে।


1
নোট করুন যে এটি ২.7-আলাদা , যেখানে start:stopঅন্তর্নির্মিত ধরণের একটি স্লাইস সহ যায় tup[:]না BINARY_SUBSCR। যদিও বর্ধিত কাটাটি start:stop:stepসাবস্ক্রিপশনটির মধ্য দিয়ে যায়।
উইম

ঠিক আছে, পাইথন সংস্করণ নির্দিষ্ট করতে ধন্যবাদ আপডেট হবে।
ফখর মোকাদেমে

0

এটি সম্পর্কে নিশ্চিত নয় তবে মনে হচ্ছে পাইথন আপনাকে একই জিনিসটিতে একটি নতুন পয়েন্টার সরবরাহ করে যাতে কপিগুলি এড়ানোর জন্য যেহেতু টিউপসগুলি অভিন্ন (এবং যেহেতু বস্তুটি একটি টিউপল, এটি পরিবর্তনযোগ্য)।

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