পাইথনের "ইজ" অপারেটর বোঝা


109

isঅপারেটর ভেরিয়েবলের মান কিন্তু দৃষ্টান্ত নিজেদের সাথে মিলছে না।

আসলেই এর অর্থ কী?

আমি দুটি ভেরিয়েবলের নামকরণ xএবং yএকই মান নির্ধারণের জন্য দুটি ভেরিয়েবল ঘোষণা করেছিলাম , তবে isঅপারেটরটি ব্যবহার করার সময় এটি মিথ্যা প্রত্যাবর্তন করে ।

আমার একটা ব্যাখ্যা দরকার এখানে আমার কোড।

x = [1, 2, 3]
y = [1, 2, 3]

print(x is y)  # It prints false!

সংশ্লিষ্ট প্রশ্ন stackoverflow.com/questions/38189660/...
Kasravnd

উত্তর:


181

isঅপারেটর যা পরীক্ষা করে তা আপনি ভুল বুঝে ফেলেছেন। এটি পরীক্ষা করে যদি দুটি ভেরিয়েবল একই বস্তুটিকে নির্দেশ করে তবে দুটি ভেরিয়েবলের একই মান হয় না।

isঅপারেটরের জন্য ডকুমেন্টেশন থেকে :

অপারেটার isএবং is notবস্তুর পরিচয়ের জন্য পরীক্ষা: x is yযদি এবং কেবল যদি সত্য xএবং yএকই বস্তুর হয়।

ব্যবহার করুন ==পরিবর্তে অপারেটর:

print(x == y)

এই মুদ্রণ Truexএবং yদুটি পৃথক তালিকা:

x[0] = 4
print(y)  # prints [1, 2, 3]
print(x == y)   # prints False

আপনি যদি id()ফাংশনটি ব্যবহার করেন আপনি তা দেখতে পাবেন xএবং yআলাদা আলাদা শনাক্তকারী রয়েছে:

>>> id(x)
4401064560
>>> id(y)
4401098192

তবে আপনি যদি নির্ধারিত yহন xতবে উভয়ই একই বস্তুর দিকে নির্দেশ করুন:

>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True

এবং isদেখায় যে উভয়ই একই জিনিস, এটি ফিরে আসে True

মনে রাখবেন পাইথনে, নামগুলি কেবলমাত্র উল্লেখের মানগুলি উল্লেখ করে ; আপনি একই জিনিস একাধিক নাম পয়েন্ট করতে পারেন। isদুটি নাম যদি একটি এবং একই অবজেক্টের দিকে নির্দেশ করে তবে আপনাকে জানায়। ==আপনাকে বলে যে দুটি নাম যদি একই রকম মানযুক্ত অবজেক্টগুলিকে উল্লেখ করে।


13
সুতরাং, A is Bহিসাবে একই id(A) == id(B)
imallett

2
@ মিমলেট: এটি একই পরীক্ষার জন্য প্রক্সি, আপনি id(A)যদি কোনও পরিবর্তনশীল না সঞ্চয় করেন এবং পরে variable == id(B)এখনও কাজ করার আশা না করেন তবে; যদি এর Aমধ্যে মুছে ফেলা হয় তবে Bএকই মেমরির অবস্থান দেওয়া যেতে পারত।
মার্টিজন পিটারস

1
মন্তব্যে ফর্ম্যাট করা যায়নি। তবে একটি আকর্ষণীয় জিনিস আছে। :) >>> x = 5 \n>>> y = 5 \n>>> x হ্যাঁ \nসত্য \n>>> x == y \nসত্য \n>>>\n
হারাণধ

5
ছোট সংখ্যক সিপিথনে অভ্যন্তরীণ হয় কারণ এটি প্রায়শই ব্যবহৃত হয়। এটি একটি অপ্টিমাইজেশন। x = 5; y = 5; x হল y => সত্য কারণ আইডি (এক্স) == আইডি (y)। এটি একই পূর্ণসংখ্যার বস্তু যা পুনরায় ব্যবহৃত হয়। পাইথনে কাজ করে যেহেতু পূর্ণসংখ্যার পরিবর্তন হয় না। যদি আপনি x = 1.0 করেন; y = 1.0 বা x = 9999; y = 9999, এটি একই পরিচয় হবে না, কারণ ভাসমান এবং বড় আকারের অন্তর্নির্মিত হয় না।
ম্যাগনাস লাইকå

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

60

অন্য সদৃশটি জিজ্ঞাসা করছিল কেন দুটি সমান স্ট্রিং সাধারণত অভিন্ন হয় না, যার উত্তর এখানে পাওয়া যায় না:

>>> x = 'a' 
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False

সুতরাং, কেন তারা একই স্ট্রিং হয় না? বিশেষত এটি দেওয়া:

>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True

দ্বিতীয় অংশটি কিছুটা বন্ধ রেখে দেওয়া যাক। প্রথমটি কীভাবে সত্য হতে পারে?

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

আর পাইথন হয়েছে একটি স্ট্রিং টেবিল interning; আপনি নিজেই sys.internপদ্ধতিতে স্ট্রিং ইন্টার্ন করতে পারেন ।

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

সিপিথন (আপনি যে প্রয়োগটি ব্যবহার করছেন তা যদি আপনি জানেন না তবে আপনি কী ব্যবহার করছেন) অটো-ইন্টার্নগুলি ছোট ছোট পূর্ণসংখ্যা এবং কিছু বিশেষ সিঙ্গেলন পছন্দ করে Falseতবে স্ট্রিং নয় (বা বড় পূর্ণসংখ্যা বা ছোট্ট টিউপস বা অন্য কিছু)। আপনি এটি খুব সহজেই দেখতে পাবেন:

>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False

ঠিক আছে, তবে কেন zএবং wঅভিন্ন ছিল?

এটি দোভাষী স্বয়ংক্রিয়ভাবে ইন্টার্নিং নয়, এটি সংকলক ভাঁজ মানগুলি।

একই কম্পাইল-টাইম স্ট্রিং একই মডিউলে দুইবার মনে হচ্ছে, যদি (ঠিক এর মানে সংজ্ঞায়িত এটা একটি স্ট্রিং আক্ষরিক একই জিনিস নয় কঠিন কারণ r'abc', 'abc'এবং'a' 'b' 'c' সব বিভিন্ন লিটারেল কিন্তু একই স্ট্রিং-কিন্তু সহজ বুঝতে স্বজ্ঞাতভাবে), সংকলকটি দুটি রেফারেন্স সহ কেবল স্ট্রিংয়ের একটি উদাহরণ তৈরি করবে।

আসলে, সংকলকটি আরও এগিয়ে যেতে পারে: অপ্টিমাইজার দ্বারা 'ab' + 'c'রূপান্তরিত হতে পারে 'abc', 'abc'এক্ষেত্রে এটি একই মডিউলের একটি ধ্রুবকের সাথে একসাথে ভাঁজ করা যেতে পারে ।

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


সুতরাং, আপনি প্রোগ্রামার হিসাবে এই সম্পর্কে কি করা উচিত?

যাইহোক কিছুই না. দুটি অপরিবর্তনীয় মান অভিন্ন হলে আপনার যত্ন নেওয়ার কোনও কারণ নেই have আপনি যদি a is bপরিবর্তে কখন ব্যবহার করতে পারেন a == bতা জানতে চাইলে আপনি ভুল প্রশ্ন জিজ্ঞাসা করছেন। a == bদুটি ক্ষেত্রে বাদে কেবল সর্বদা ব্যবহার করুন :

  • আরও পড়তে পারা তুলনার জন্য সিঙ্গলটন মানগুলির মতো x is None
  • পরিবর্তনীয় মানগুলির জন্য, যখন আপনাকে জানতে হবে পরিবর্তনগুলি xপ্রভাবিত করবে কিনা y

1
দুর্দান্ত ব্যাখ্যা, বিশেষত শেষে আপনার পরামর্শ।
ডেভিডজি

বিস্তারিত ব্যাখ্যা করার জন্য আপনাকে ধন্যবাদ। কেউ কি জানেন: সংকলক ভাঁজ মানগুলির কারণে wএবং যদি zএটি অভিন্ন হয় তবে কেন id()এটি রেফারেন্সগুলি পরীক্ষা করে ব্যবহার করে এমনকি আরপিএল-এও কাজ করে ? পাইথন ৩.7
-

8

isযদি সত্যই তারা একই জিনিস হয় তবেই সত্যটি প্রত্যাবর্তন করে। যদি সেগুলি একই হয় তবে একজনের মধ্যে অন্যটির পরিবর্তনও দেখাতে পারে। পার্থক্যের একটি উদাহরণ এখানে।

>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]

8

একটি সদৃশ প্রশ্ন দ্বারা প্রম্পট , এই উপমা কাজ করতে পারে:

# - Darling, I want some pudding!
# - There is some in the fridge.

pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True

# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.

pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False

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

1
@ টমক্লোজ: এই প্রশ্নে অনেক সূক্ষ্ম উত্তর রয়েছে, যাতে যথাযোগ্যতার জন্য জায়গা থাকে। এছাড়াও, আমি পুডিংও চাই।
আমদান

5

isএবং is notপাইথনের দুটি পরিচয় অপারেটর। isঅপারেটর ভেরিয়েবলের মানগুলির তুলনা করে না, তবে ভেরিয়েবলের পরিচয়ের তুলনা করে। এই বিবেচনা:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> hex(id(a))
'0x1079b1440'
>>> hex(id(b))
'0x107960878'
>>> a is b
False
>>> a == b
True
>>>

উপরের উদাহরণটি আপনাকে দেখায় যে পরিচয়টি (সিপিথনের মেমরি ঠিকানাও হতে পারে) উভয়ের জন্য aএবং b(তাদের মান একই হলেও ) আলাদা । এ কারণেই যখন আপনি বলবেন যে a is bএটি উভয় অপারেন্ডের পরিচয় মিলছে না false তবে আপনি যখন বলবেন a == b, এটি সত্য প্রত্যাবর্তন করে কারণ ==অপারেশন কেবলমাত্র উভয় অপারেন্ডের কাছে তাদের একই মূল্য নির্ধারিত থাকলে তা যাচাই করে।

আকর্ষণীয় উদাহরণ (অতিরিক্ত গ্রেডের জন্য):

>>> del a
>>> del b
>>> a = 132
>>> b = 132
>>> hex(id(a))
'0x7faa2b609738'
>>> hex(id(b))
'0x7faa2b609738'
>>> a is b
True
>>> a == b
True
>>>

উপরের উদাহরণে, যদিও aএবং bদুটি পৃথক ভেরিয়েবল, a is bফিরে এসেছে True। এই কারণে ধরনের aহয় intযা অপরিবর্তনীয় অবজেক্ট। সুতরাং পাইথন (আমি মনে করি মেমরিটি সংরক্ষণ করার জন্য) একই বস্তুটি bযখন এটি একই মান দিয়ে তৈরি হয়েছিল তখন বরাদ্দ করে । সুতরাং এই ক্ষেত্রে, ভেরিয়েবলগুলির পরিচয় মিলেছে এবং a is bপরিণত হয়েছে True

এটি সমস্ত অপরিবর্তনীয় বস্তুর জন্য প্রযোজ্য:

>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>

আশা করি এইটি কাজ করবে.


এটি বাস্তব সুন্দর উদাহরণ। বিস্তারিত তথ্যের জন্য ধন্যবাদ।
হারাণধ

তবে একটি = 123456789 বি = 123456789
ইউজার 2183078

পাইথনের -5চেয়ে কম বা তার চেয়ে বেশি কিছু 256মিথ্যা হবে। পাইথন সংখ্যায় ক্যাচ করে [-5, 256]।
স্মার্ট

আপনার প্রদর্শিত হিসাবে সমস্ত অপরিবর্তনীয় অবজেক্টগুলি ভাগ করা হবে না, এটি কিছু অপজেক্টের জন্য পাইথন রানটাইম দ্বারা প্রয়োগ করা একটি অপ্টিমাইজেশন তবে অন্যদের নয়। ছোট পূর্ণসংখ্যা ভাগ করার প্রক্রিয়াটি ভালভাবে নথিবদ্ধ, তবে আমি মনে করি না এটি স্ট্রিং ইন্টার্নিংয়ের জন্য
মার্ক রান্সম

4

x is yid(x) == id(y)বস্তুর পরিচয় তুলনা হিসাবে একই ।

@ টমাস-কুর্গান যেমন নীচের মন্তব্যে উল্লেখ করেছেন isঅপারেটর নির্দিষ্ট কিছু বস্তুর সাথে অস্বাভাবিক আচরণ করে।

যেমন

>>> class A(object):
...   def foo(self):
...     pass
... 
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True

সূত্র;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/references/expressions.html#id24


না, তা হয় না। এটি বেশিরভাগ ক্ষেত্রে একই রকম আচরণ করতে পারে তবে এটি সর্বদা সত্য নয়। দেখুন এই - পৃষ্ঠার খুব নীচে, বুলেট 6 .:> (...), আপনি নির্দিষ্ট ব্যবহারসমূহ মধ্যে আপাতদৃষ্টিতে অস্বাভাবিক আচরণ খেয়াল করতে পারেন এর হয় অপারেটর, উদাহরণস্বরূপ পদ্ধতি, বা ধ্রুবক এবং সংক্ষিপ্ত পরিশ্রমী উদাহরণ মধ্যে যারা জড়িত তুলনা মত : `শ্রেণি এ (অবজেক্ট): ডিফ ফু (স্ব): পাস এ = এ () প্রিন্ট a.foo হ'ল a.foo প্রিন্ট আইডি (a.foo) == আইডি (a.foo)`
টমাসজ কুর্গান

3

আপনি এখানে একটি ছোট পূর্ণসংখ্যার চেক করতে পারেন। 257 এর উপরে সংখ্যাগুলি কোনও ছোট ints নয়, সুতরাং এটি একটি পৃথক অবজেক্ট হিসাবে গণনা করা হয়।

==এই ক্ষেত্রে পরিবর্তে ব্যবহার করা ভাল is

আরও তথ্য এখানে: http://docs.python.org/2/c-api/int.html


2

এক্স বিন্যাসে একটি অ্যারে, ওয়াই আলাদা অ্যারেতে নির্দেশ করে। এই অ্যারেগুলি অভিন্ন, তবে isঅপারেটর সেই পয়েন্টারগুলিকে দেখবে, যা অভিন্ন নয়।


5
পাইথনের পয়েন্টার নেই। আপনাকে আপনার পরিভাষাটি আরও শক্ত করতে হবে।
ডেভিড হেফারনন

3
এটি জাভা এবং অন্যান্য অনেক ভাষার মতো অভ্যন্তরীণভাবে করে। আসলে, isঅপারেটরের কার্যকারিতা এটি দেখায়।
নেকো

5
বাস্তবায়ন বিবরণ কি গুরুত্বপূর্ণ তা নয়। ডকুমেন্টেশনটি "অবজেক্ট আইডেন্টিটি" শব্দটি ব্যবহার করে। আপনারও উচিত। "অপারেটরগুলি অবজেক্টের সনাক্তকরণের জন্য পরীক্ষা করা হয় না: x এবং y একই হয় এবং x এবং y একই বস্তু হয় তবে x নয় y এর বিপরীত সত্যের মান দেয়" "
ডেভিড হেফারনান

1
@ নেকো: সিপিথন অভ্যন্তরীণভাবে পয়েন্টার ব্যবহার করে। তবে স্পষ্টতই জাইথন ​​(জাভাতে প্রয়োগ করা হয়েছে) এবং পাইপাই (পাইথনের উপসেটে প্রয়োগ করা হয়েছে) পয়েন্টার ব্যবহার করবেন না। পাইপাইতে, কিছু জিনিসগুলির কাছে এমনটি থাকবে না idযতক্ষণ না আপনি তা জিজ্ঞাসা করেন।
abarnert

1

এটি অবজেক্ট আইডেন্টিটির সাথে তুলনা করে, অর্থাৎ, ভেরিয়েবলগুলি মেমরিতে একই বস্তুকে বোঝায় কিনা। এটি ==জাভা বা সি এর মতো (পয়েন্টারগুলির সাথে তুলনা করার সময়)।


1

ফল সহ একটি সহজ উদাহরণ

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )

আউটপুট:

True
False
False

যদি তুমি চেষ্টা কর

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )

আউটপুট পৃথক:

True
True
True

কারণ == অপারেটর কেবল ভেরিয়েবলের বিষয়বস্তুর সাথে তুলনা করে। 2 ভেরিয়েবল ব্যবহার পরিচয় তুলনা করতে হয় অপারেটর

পরিচয় নম্বর প্রিন্ট করতে:

print ( id( variable ) )

-3

isঅপারেটর কিছুই কিন্তু এর একটি ইংরেজি সংস্করণ ==। কারণ দুটি তালিকার আইডি আলাদা তাই উত্তরটি মিথ্যা। আপনি চেষ্টা করতে পারেন:

a=[1,2,3]
b=a
print(b is a )#True

* কারণ উভয় তালিকার আইডি একই হবে


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