খ তালিকাভুক্ত হলে কেন খ + = (4,) কাজ করে এবং খ = বি + (4,) কাজ করে না?


77

যদি আমরা গ্রহণ করি b = [1,2,3]এবং যদি আমরা চেষ্টা করি:b+=(4,)

এটি ফিরে আসে b = [1,2,3,4], তবে আমরা চেষ্টা করে দেখলে b = b + (4,)এটি কার্যকর হয় না।

b = [1,2,3]
b+=(4,) # Prints out b = [1,2,3,4]
b = b + (4,) # Gives an error saying you can't add tuples and lists

b+=(4,)আপনি একটি তালিকা এবং একটি টিপল যোগ করতে না পারায় আমি ব্যর্থ হওয়ার প্রত্যাশা করেছি , তবে এটি কার্যকর হয়েছে। তাই আমি b = b + (4,)একই ফল পাওয়ার আশা করার চেষ্টা করেছি , তবে এটি কার্যকর হয়নি।


4
আমি বিশ্বাস করি এখানে একটি উত্তর পাওয়া যাবে
জোচেন


প্রথমে আমি এটি ভুলভাবে পড়েছি এবং এটি খুব বিস্তৃত হিসাবে বন্ধ করার চেষ্টা করেছি, তারপরে এটি প্রত্যাহার করে নিয়েছি। তারপরে আমি ভেবেছিলাম এটি একটি সদৃশ হতে হবে, তবে আমি কেবল পুনরায় ভোট দিতে পারিনি, আমি তাদের মতো উত্তরগুলি খুঁজতে চেষ্টা করে আমার চুল টেনে নিলাম। : /
কার্ল নচেটেল

অত্যন্ত অনুরূপ প্রশ্ন: stackoverflow.com/questions/58048664/...
sanyash

উত্তর:


70

"কেন" প্রশ্নগুলির সমস্যাটি হ'ল সাধারণত তারা একাধিক ভিন্ন জিনিস বোঝাতে পারে। আমি মনে করি আপনার মনে থাকতে পারে এমন প্রত্যেকটির উত্তর দেওয়ার চেষ্টা করব।

"কেন এটির পক্ষে আলাদাভাবে কাজ করা সম্ভব?" যার উত্তর দেওয়া হয় এই দ্বারা । মূলত, +=অবজেক্টের বিভিন্ন পদ্ধতি ব্যবহার করার চেষ্টা করে: __iadd__(যা কেবলমাত্র বাম-হাতের দিকে পরীক্ষা করা হয়), বনাম __add__এবং __radd__("বিপরীত অ্যাড", বাম-হাতের অংশটি না থাকলে ডানদিকে চেক করা হয় __add__) জন্য +

"প্রতিটি সংস্করণ ঠিক কী করে?" সংক্ষেপে, list.__iadd__পদ্ধতিটি একই কাজ করে list.extend(তবে ভাষা নকশার কারণে এখনও একটি অ্যাসাইনমেন্ট ফিরে আসে)।

এটি উদাহরণস্বরূপ এর অর্থও

>>> a = [1,2,3]
>>> b = a
>>> a += [4] # uses the .extend logic, so it is still the same object
>>> b # therefore a and b are still the same list, and b has the `4` added
[1, 2, 3, 4]
>>> b = b + [5] # makes a new list and assigns back to b
>>> a # so now a is a separate list and does not have the `5`
[1, 2, 3, 4]

+অবশ্যই, একটি নতুন অবজেক্ট তৈরি করে, তবে স্পষ্টতই উপাদানগুলিকে ভিন্ন ক্রম থেকে বের করার চেষ্টা করার পরিবর্তে অন্য তালিকার প্রয়োজন।

"এটি করার জন্য কেন এটি দরকারী? এটি আরও দক্ষ; extendপদ্ধতিতে কোনও নতুন অবজেক্ট তৈরি করতে হবে না, অবশ্যই এর কিছু আশ্চর্যজনক প্রভাব রয়েছে (কখনও কখনও উপরের মতো), এবং সাধারণত পাইথন দক্ষতার বিষয়ে নয় really , তবে এই সিদ্ধান্তগুলি অনেক আগে হয়েছিল।

"তালিকাগুলি এবং + সহ টুপলগুলি যোগ না করার কারণ কী?" এখানে দেখুন (ধন্যবাদ, @ splash58); একটি ধারণা হ'ল (tuple + list) একই ধরণের (list + tuple) উত্পাদন করা উচিত এবং ফলাফলটি কোন ধরণের হওয়া উচিত তা পরিষ্কার নয়। +=এই সমস্যা নেই, কারণ a += bস্পষ্টতই ধরণের পরিবর্তন করা উচিত নয় a


2
ওফ, বেশ ঠিক। এবং তালিকাগুলি ব্যবহার করে না |, যাতে কান্ডা আমার উদাহরণটি নষ্ট করে দেয়। যদি আমি এর থেকে আরও পরিষ্কার উদাহরণটি মনে করি তবে পরে এটিকে সরিয়ে নেব
কার্ল নচেটেল

1
|সেটগুলির জন্য বিটিডব্লিউ একটি আসন্ন অপারেটর তবে +তালিকার জন্য নয়। যে কারণে আমি মনে করি না টাইপ অস্পষ্টতা সম্পর্কে তর্কটি বিশেষভাবে শক্তিশালী। অপারেটর যেহেতু যাতায়াত করে না কেন প্রকারের জন্য একই প্রয়োজন হয়? যে কেউ একমত হতে পারে যে ফলাফলটির lhs ধরণের রয়েছে। অন্যদিকে, সীমাবদ্ধ করে list + iterator, বিকাশকারী তাদের উদ্দেশ্য সম্পর্কে আরও সুস্পষ্ট হতে উত্সাহিত করা হয়। যদি আপনি একটি নতুন তালিকা যে কাপড় থেকে ধারণ করে তৈরি করতে চান তাহলে aকাপড় দ্বারা বর্ধিত থেকে bইতিমধ্যেই এই কাজ করতে একটি উপায় আছে: new = a.copy(); new += b। এটি আরও একটি লাইন তবে স্ফটিক পরিষ্কার।
a_guest

দক্ষতার a += bচেয়ে ভিন্ন আচরণ করার কারণটি a = a + bদক্ষতা নয়। এটি আসলে যে গুইডো বেছে নেওয়া আচরণকে কম বিভ্রান্তিকর বলে মনে করেছিলেন। কোনও ফাংশনটি aআর্গুমেন্ট হিসাবে একটি তালিকা পেয়ে এবং তারপরে কল্পনা করুন a += [1, 2, 3]। এই বাক্যবিন্যাসটি অবশ্যই দেখে মনে হচ্ছে এটি নতুন তালিকা তৈরির পরিবর্তে তালিকায় স্থান পরিবর্তন করছে, সুতরাং সিদ্ধান্ত নেওয়া হয়েছিল যে প্রত্যাশিত ফলাফল সম্পর্কে বেশিরভাগ মানুষের অন্তর্নিহিত অনুযায়ী আচরণ করা উচিত। যাইহোক, প্রক্রিয়াটিকে এসগুলির মতো অপরিবর্তনীয় ধরণের জন্যও কাজ করতে হয়েছিল int, যা বর্তমান নকশার দিকে পরিচালিত করেছিল।
সোভেন মারনাচ

আমি ব্যক্তিগতভাবে মনে করি যে নকশাটি আসলে রুবির মতো একটি সংক্ষিপ্তকরণ তৈরির চেয়ে বেশি বিভ্রান্তিকর , তবে আমরা বুঝতে পারি যে আমরা সেখানে কীভাবে এসেছি। a += ba = a + b
সোভেন মারনাচ

21

এগুলি সমতুল্য নয়:

b += (4,)

সংক্ষিপ্ত জন্য:

b.extend((4,))

+তালিকাগুলি সংঘবদ্ধ করার সময় তাই:

b = b + (4,)

আপনি একটি তালিকায় একটি tuple মনস্থির চেষ্টা করছেন


14

আপনি যখন এটি করবেন:

b += (4,)

এটি রূপান্তরিত হয়:

b.__iadd__((4,)) 

ফণা এটা আহ্বান অধীনে b.extend((4,)), extendকোনো ইটারেটরে গ্রহণ করে এবং কেন এই কাজ:

b = [1,2,3]
b += range(2)  # prints [1, 2, 3, 0, 1]

তবে আপনি যখন এটি করেন:

b = b + (4,)

এটি রূপান্তরিত হয়:

b = b.__add__((4,)) 

শুধুমাত্র তালিকা অবজেক্ট গ্রহণ করুন।


4

সরকারী দস্তাবেজগুলি থেকে, উভয় পরিবর্তনীয় ক্রমের জন্য :

s += t
s.extend(t)

হিসাবে সংজ্ঞায়িত করা হয়:

sএর বিষয়বস্তু সহ প্রসারিতt

যা সংজ্ঞায়িত হওয়ার চেয়ে পৃথক:

s = s + t    # not equivalent in Python!

এর অর্থ হ'ল যে কোনও সিক্যুয়েন্স টাইপt আপনার উদাহরণের মতো একটি টিপল সহ কাজ করবে

তবে এটি ব্যাপ্তি এবং জেনারেটরের জন্যও কাজ করে! উদাহরণস্বরূপ, আপনি এটি করতে পারেন:

s += range(3)

3

+=পাইথন ২.০-তে "অগমেন্টেড" এসাইনমেন্ট অপারেটরগুলি প্রবর্তিত হয়েছিল, যা ২০০০ সালের অক্টোবরে প্রকাশিত হয়েছিল। ডিজাইন এবং যুক্তিগুলি পিইপি ২০৩-এ বর্ণনা করা হয়েছে । এই অপারেটরগুলির ঘোষিত লক্ষ্যগুলির একটি হ'ল ইন-প্লেস অপারেশনগুলির সমর্থন। লেখা

a = [1, 2, 3]
a += [4, 5, 6]

a জায়গাটি তালিকায় আপডেট করার কথা । তালিকার অন্যান্য উল্লেখ রয়েছে তবে এটি গুরুত্বপূর্ণ a, যেমন aফাংশন আর্গুমেন্ট হিসাবে কখন প্রাপ্ত হয়েছিল।

যাইহোক, অপারেশনটি সর্বদা স্থানে হতে পারে না, যেহেতু পূর্ণসংখ্যা এবং স্ট্রিং সহ পাইথনের অনেক ধরণ অপরিবর্তনীয় , সুতরাং উদাহরণস্বরূপ i += 1কোনও পূর্ণসংখ্যার জন্য iসম্ভবত জায়গায় কাজ করা যায় না।

সংক্ষেপে, অগমেন্টেড অ্যাসাইনমেন্ট অপারেটররা যখন সম্ভব হবে তখন জায়গায় কাজ করবে এবং অন্যথায় একটি নতুন অবজেক্ট তৈরি করার কথা ছিল। এই নকশা লক্ষ্যগুলি সুবিধার জন্য, প্রকাশটি নীচের x += yমতো আচরণের জন্য নির্দিষ্ট করা হয়েছিল:

  • যদি x.__iadd__সংজ্ঞায়িত x.__iadd__(y)হয় তবে মূল্যায়ন করা হয়।
  • অন্যথায়, x.__add__বাস্তবায়িত হলে x.__add__(y)মূল্যায়ন করা হয়।
  • অন্যথায়, y.__radd__বাস্তবায়িত হলে y.__radd__(x)মূল্যায়ন করা হয়।
  • অন্যথায় একটি ত্রুটি উত্থাপন।

এই প্রক্রিয়াটির দ্বারা প্রাপ্ত প্রথম ফলাফলটি আবার বরাদ্দ করা হবে x(যদি না ফলাফলটি NotImplementedসিঙ্গলটন না হয় তবে সেক্ষেত্রে পরবর্তী পদক্ষেপের সাথে অনুসন্ধান অব্যাহত থাকে)।

এই প্রক্রিয়া ধরনের যে সমর্থনে জায়গা পরিবর্তন বাস্তবায়ন করতে পারবেন __iadd__()। প্রকারভেদ যে না ইন-জায়গা পরিবর্তন সমর্থন কোনো নতুন জাদু পদ্ধতি যোগ করার জন্য, যেহেতু পাইথন স্বয়ংক্রিয়ভাবে মূলত ফিরে আসবে প্রয়োজন হবে না x = x + y

সুতরাং আসুন শেষ পর্যন্ত আসুন আপনার আসল প্রশ্নে - আপনি কেন একটি বর্ধিত অ্যাসাইনমেন্ট অপারেটরের সাথে তালিকায় একটি টিপল যুক্ত করতে পারেন। স্মৃতি থেকে, এর ইতিহাস মোটামুটি এর মত: list.__iadd__()পদ্ধতিটি ইতিমধ্যে list.extend()পাইথন ২.০ এ ইতিমধ্যে বিদ্যমান পদ্ধতিটি কল করার জন্য প্রয়োগ করা হয়েছিল । পাইথন ২.১-এ পুনরাবৃত্তি চালু করা হলে list.extend()নির্বিচারে পুনরাবৃত্তিকে গ্রহণ করার পদ্ধতিটি আপডেট করা হয়েছিল। এই পরিবর্তনগুলির শেষ ফলাফলটি my_list += my_tupleপাইথন ২.১ থেকে শুরু করে কাজ করেছিল। list.__add__()পদ্ধতি, কিন্তু, ডানদিকের আর্গুমেন্ট হিসাবে নির্বিচারে iterators সমর্থন করার জন্য কথা ছিল না - এই শক্তিশালী ভাবে টাইপ ভাষার জন্য অনুপযুক্ত বিবেচিত ছিল।

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

t = ([42], [43])
t[0] += [44]

দ্বিতীয় লাইনটি উত্থাপিত হয় TypeError: 'tuple' object does not support item assignment, তবে অপারেশনটি যেভাবেই সফলভাবে সম্পাদিত হয় - ত্রুটি উত্থাপনকারী লাইনটি কার্যকর করার পরে tহবে ([42, 44], [43])


বলিহারি! পিইপি সম্পর্কিত একটি রেফারেন্স থাকা বিশেষভাবে দরকারী। তালিকার অভ্যন্তরীণ আচরণ সম্পর্কে পূর্ববর্তী একটি প্রশ্নে আমি অন্য প্রান্তে একটি লিঙ্ক যুক্ত করেছি। ২.৩ বা তার আগে পাইথন কেমন ছিল তা আমি যখন ফিরে দেখি তখন আজকের তুলনায় এটি ব্যবহারিকভাবে অকেজো বলে মনে হয় ... (এবং আমি এখনও খুব পুরানো ম্যাকের জন্য দরকারী কিছু করতে 1.5 ব্যবহার করতে চেষ্টা করতে এবং ব্যর্থ করার একটি অস্পষ্ট স্মৃতি পেয়েছি)
কার্ল নচেটেল

2

বেশিরভাগ লোক X + = Y এর X = X + Y এর সমতুল্য হবেন বলে আশাবাদী Indeed এক্স + = ওয়াই "। যাইহোক, পাইথন নির্দিষ্ট করা ব্যক্তিরা তাদের সমতুল্য করেনি। সম্ভবত এটি একটি ভুল ছিল যার ফলে হতাশ প্রোগ্রামাররা যতক্ষণ না পাইথন ব্যবহার অবধি অবধি ব্যবহার করেন ততক্ষণ ধরে ডিবাগিংয়ের সময় ঘটাতে পারে তবে এটি এখন পাইথনটি ঠিক the যদি এক্স একটি পরিবর্তনীয় সিকোয়েন্স টাইপ হয় তবে এক্স + = ওয়াইটি এক্স.একস্টেন্ড (ওয়াই) এর সমান এবং এক্স = এক্স + ওয়াইয়ের সমতুল্য নয় X


> সম্ভবত এটি একটি ভুল ছিল যার ফলে হতাশ প্রোগ্রামাররা যতক্ষণ না পাইথন ব্যবহারের সময় অবধি রয়েছেন তার জন্য কয়েক ঘন্টা ডিবাগিংয়ের সময় আসবে <- আপনি কি আসলে এর কারণে ভুগছিলেন? আপনি অভিজ্ঞতা থেকে কথা বলে মনে হচ্ছে। আমি আপনার গল্প শুনতে খুব পছন্দ করি।
ভিকি

1

যেমন এটি এখানে ব্যাখ্যা করা হয়েছে , যদি পদ্ধতিটি arrayবাস্তবায়ন না __iadd__করে b+=(4,)তবে এটি কেবল একটি সংক্ষিপ্তরূপে হবে b = b + (4,)তবে স্পষ্টতই এটি তা নয়, সুতরাং পদ্ধতিটি arrayবাস্তবায়ন করে __iadd__। স্পষ্টতই __iadd__পদ্ধতিটির বাস্তবায়ন এরকম কিছু:

def __iadd__(self, x):
    self.extend(x)

তবে আমরা জানি যে উপরের কোডটি __iadd__পদ্ধতির প্রকৃত বাস্তবায়ন নয় তবে আমরা ধরে নিতে পারি এবং গ্রহণ করতে পারি যে extendপদ্ধতির মতো কিছু আছে যা tuppleইনপুট গ্রহণ করে।

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