একটি খালি তালিকা (উদাহরণস্বরূপ []] "" ") ত্রুটি কেন অর্পণ করা হচ্ছে না?


110

অজগর 3.4 এ, আমি টাইপ করছি

[] = "" 

এবং এটি ঠিক কাজ করে, কোনও ব্যতিক্রম উত্থাপিত হয় না। যদিও পরে []সমান নয় ""

[] = ()

ভাল কাজ করে।

"" = []

প্রত্যাশার মতো ব্যতিক্রম উত্থাপন যদিও

() = ""

প্রত্যাশিত হিসাবে ব্যতিক্রম উত্থাপন। তো কেমন যাচ্ছে?

উত্তর:


132

আপনি সাম্যের জন্য তুলনা করছেন না। আপনি নিয়োগ করছেন

পাইথন আপনাকে একাধিক লক্ষ্য নির্ধারণ করতে দেয়:

foo, bar = 1, 2

যথাক্রমে fooএবং দুটি মান নির্ধারণ করে bar। আপনার যা দরকার তা হ'ল ডান হাতের দিকে একটি ক্রম বা পুনরাবৃত্তিযোগ্য এবং বামে নামের একটি তালিকা বা টিপল।

যখন তুমি কর:

[] = ""

নামের শূন্য তালিকায় আপনি একটি খালি ক্রম (খালি স্ট্রিংগুলি ক্রমগুলি এখনও স্থায়ী) নিযুক্ত করেছেন।

এটি করণ হিসাবে মূলত একই জিনিস:

[foo, bar, baz] = "abc"

যেখানে আপনি দিয়ে শেষ foo = "a", bar = "b"এবং baz = "c", কিন্তু অপেক্ষাকৃত কম অক্ষর বিশিষ্ট সঙ্গে।

তবে আপনি কোনও স্ট্রিংকে বরাদ্দ করতে পারবেন না, সুতরাং ""কোনও অ্যাসাইনমেন্টের বাম দিকে কখনও কাজ করে না এবং সর্বদা একটি সিনট্যাক্স ত্রুটি থাকে।

দেখুন অ্যাসাইনমেন্ট বিবৃতি ডকুমেন্টেশন :

একটি অ্যাসাইনমেন্ট স্টেটমেন্টটি এক্সপ্রেশন তালিকার মূল্যায়ন করে (মনে রাখবেন যে এটি একটি একক অভিব্যক্তি বা কমা-বিচ্ছিন্ন তালিকা হতে পারে, পরে একটি টিউপল ফলন করে) এবং বাম থেকে ডানে প্রতিটি লক্ষ্য তালিকার একক ফলস্বরূপ অবজেক্টকে বরাদ্দ করে।

এবং

লক্ষ্য তালিকাতে অবজেক্টের নিয়োগ, parentচ্ছিকভাবে বন্ধনী বা বর্গাকার বন্ধনীতে সংযুক্ত , নীচে পুনরাবৃত্তভাবে সংজ্ঞায়িত করা হয়।

জোর আমার

পাইথন খালি তালিকার জন্য একটি সিনট্যাক্স ত্রুটি নিক্ষেপ করে না এটি আসলে কিছুটা বাগ! সরকারীভাবে নথিভুক্ত ব্যাকরণ একটি খালি লক্ষ্য তালিকার জন্য অনুমতি দেয় না, এবং খালিটির জন্য ()আপনি একটি ত্রুটি পান। বাগ 23275 দেখুন ; এটিকে একটি নিরীহ ত্রুটি হিসাবে বিবেচনা করা হয়:

শুরুর পয়েন্টটি স্বীকৃতি দিচ্ছে যে এটি খুব দীর্ঘ সময় ধরে রয়েছে এবং নিরীহ।

এছাড়াও দেখুন কেন একটি খালি তালিকায় নিয়োগ দেওয়া বৈধ তবে খালি টিপলকে নয়?


36

এটি দলিল থেকে অ্যাসাইনমেন্ট স্টেটমেন্ট বিভাগের নিয়ম অনুসরণ করে ,

assignment_stmt ::=  (target_list "=")+ (expression_list | yield_expression)

যদি target listলক্ষ্যগুলির একটি কমা-বিচ্ছিন্ন তালিকা: লক্ষ্য তালিকায় লক্ষ্যমাত্রা রয়েছে তেমন বস্তুটি অবশ্যই একই সংখ্যার আইটেমের সাথে পুনরাবৃত্ত হওয়া উচিত এবং আইটেমগুলি বাম থেকে ডানে সম্পর্কিত লক্ষ্যগুলিতে নির্ধারিত হয়।

লক্ষ্য তালিকায় লক্ষ্যবস্তু যেমন আছে তেমন সংখ্যার আইটেমের সাথে অবশ্যই বস্তুটি অবশ্যই একটি ক্রম হতে হবে এবং আইটেমগুলি বাম থেকে ডানে সম্পর্কিত লক্ষ্যগুলিতে নির্ধারিত হয়।

সুতরাং, যখন আপনি বলেন

[] = ""

"" একটি পুনরাবৃত্তযোগ্য (কোনও বৈধ পাইথন স্ট্রিং একটি পুনরাবৃত্তযোগ্য) এবং এটি তালিকার উপাদানগুলিতে প্যাক করা হচ্ছে।

উদাহরণ স্বরূপ,

>>> [a, b, c] = "123"
>>> a, b, c
('1', '2', '3')

যেহেতু আপনার একটি খালি স্ট্রিং এবং একটি খালি তালিকা রয়েছে তাই আনপ্যাক করার মতো কিছুই নেই। সুতরাং, কোন ত্রুটি।

তবে, এই চেষ্টা করুন

>>> [] = "1"
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: too many values to unpack (expected 0)
>>> [a] = ""
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: need more than 0 values to unpack

সেক্ষেত্রে [] = "1"আপনি "1"ভেরিয়েবলের খালি তালিকায় স্ট্রিংটি আনপ্যাক করার চেষ্টা করছেন । সুতরাং এটি "আনপ্যাক করার অনেক বেশি মান (প্রত্যাশিত 0)" এর সাথে অভিযোগ করে।

একইভাবে, [a] = ""ক্ষেত্রে, আপনার কাছে খালি স্ট্রিং রয়েছে, তাই সত্যিই আনপ্যাক করার মতো কিছুই নেই তবে আপনি এটি একটি ভেরিয়েবলের উপর দিয়ে আনপ্যাক করছেন, যা আবার সম্ভব নয়। এ কারণেই এটি অভিযোগ করে যে "আনপ্যাক করার জন্য 0 টিরও বেশি মানের প্রয়োজন"।

এগুলি ছাড়াও, যেমন আপনি লক্ষ্য করেছেন,

>>> [] = ()

কোনও ত্রুটিও ছুঁড়ে না, কারণ ()এটি একটি খালি টিপল।

>>> ()
()
>>> type(())
<class 'tuple'>

এবং যখন এটি খালি তালিকায় প্যাক করা হয় তখন আনপ্যাক করার কিছু নেই। সুতরাং কোন ত্রুটি।


কিন্তু, আপনি যখন করবেন

>>> "" = []
  File "<input>", line 1
SyntaxError: can't assign to literal
>>> "" = ()
  File "<input>", line 1
SyntaxError: can't assign to literal

ত্রুটি বার্তাটি যেমন বলেছে, আপনি একটি স্ট্রিংকে আক্ষরিক অর্পণ করার চেষ্টা করছেন। যা সম্ভব নয়। এজন্য আপনি ত্রুটিগুলি পাচ্ছেন। এটা বলার মতো

>>> 1 = "one"
  File "<input>", line 1
SyntaxError: can't assign to literal

internals

অভ্যন্তরীণভাবে, এই অ্যাসাইনমেন্ট অপারেশনটি UNPACK_SEQUENCEওপ কোডে অনুবাদ করা হবে ,

>>> dis(compile('[] = ""', "string", "exec"))
  1           0 LOAD_CONST               0 ('')
              3 UNPACK_SEQUENCE          0
              6 LOAD_CONST               1 (None)

এখানে, যেহেতু স্ট্রিংটি খালি, UNPACK_SEQUENCEপ্যাকেজগুলি প্যাকেজ 0বার করে। তবে আপনার যখন এই জাতীয় কিছু থাকে

>>> dis(compile('[a, b, c] = "123"', "string", "exec"))
  1           0 LOAD_CONST               0 ('123')
              3 UNPACK_SEQUENCE          3
              6 STORE_NAME               0 (a)
              9 STORE_NAME               1 (b)
             12 STORE_NAME               2 (c)
             15 LOAD_CONST               1 (None)
             18 RETURN_VALUE

ক্রমটি 123ডান থেকে বামে স্ট্যাকের মধ্যে প্যাক করা হয়। সুতরাং, স্ট্যাকের শীর্ষটি হবে 1এবং পরবর্তীটি হবে 2এবং সর্বশেষটি হবে 3। তারপরে এটি স্ট্যাকের শীর্ষ থেকে বাম পাশের অভিব্যক্তিটি একে একে একে ভেরিয়েবলগুলিকে নির্ধারণ করে।


পাইথনে বিটিডাব্লু, আপনি একই এক্সপ্রেশনটিতে একাধিক অ্যাসাইনমেন্ট করতে পারেন। উদাহরণ স্বরূপ,

a, b, c, d, e, f = u, v, w, x, y, z

এটি কাজ করে কারণ ডান হাতের মানগুলি একটি টিউপল তৈরি করতে ব্যবহৃত হয় এবং তারপরে এটি বাম হাতের মানগুলির সাথে প্যাক করা হবে।

>>> dis(compile('a, b, c, d, e, f = u, v, w, x, y, z', "string", "exec"))
  1           0 LOAD_NAME                0 (u)
              3 LOAD_NAME                1 (v)
              6 LOAD_NAME                2 (w)
              9 LOAD_NAME                3 (x)
             12 LOAD_NAME                4 (y)
             15 LOAD_NAME                5 (z)
             18 BUILD_TUPLE              6
             21 UNPACK_SEQUENCE          6
             24 STORE_NAME               6 (a)
             27 STORE_NAME               7 (b)
             30 STORE_NAME               8 (c)
             33 STORE_NAME               9 (d)
             36 STORE_NAME              10 (e)
             39 STORE_NAME              11 (f)
             42 LOAD_CONST               0 (None)
             45 RETURN_VALUE

তবে ক্লাসিক অদলবদল কৌশল a, b = b, aস্ট্যাকের শীর্ষে উপাদানগুলির ঘূর্ণন ব্যবহার করে। আপনার যদি কেবল দুটি বা তিনটি উপাদান থাকে তবে এগুলিকে টিপল তৈরি এবং আনপ্যাকিংয়ের পরিবর্তে বিশেষ ROT_TWOএবং ROT_THREEনির্দেশাবলীর সাথে চিকিত্সা করা হবে।

>>> dis(compile('a, b = b, a', "string", "exec"))
  1           0 LOAD_NAME                0 (b)
              3 LOAD_NAME                1 (a)
              6 ROT_TWO
              7 STORE_NAME               1 (a)
             10 STORE_NAME               0 (b)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE

আপনি dis('[] = ""')কল না করেও ব্যবহার করতে পারবেন compile()
Andrea Corbellini

আপনি যদি আপনার শেষ উদাহরণটিতে এই পদ্ধতিটি ব্যবহার করে তিনটিরও বেশি ভেরিয়েবল / উপাদানগুলিকে অদলবদল করে থাকেন তবে কী ঘটতে পারে তা আপনি বর্ণনা করতে পারেন?
ন্যানোফারাড

@ হেক্সাফ্রাকশন এটি ডান হাতের সমস্ত উপাদানগুলির সাথে একটি নতুন টুপল তৈরি করবে এবং তারপরে এটি বাম হাতের ভেরিয়েবলগুলির উপরে আনপ্যাক করবে।
thefourtheye

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