কেন `যদি কেউ না থাকে।


146

যদি আপনি পাইথন ৩.7-তে নিম্নলিখিত বিবৃতিটি কার্যকর করেন তবে এটি (আমার পরীক্ষা থেকে) মুদ্রণ হবে b:

if None.__eq__("a"):
    print("b")

যাইহোক, None.__eq__("a")মূল্যায়ন NotImplemented

স্বাভাবিকভাবেই, এর "a".__eq__("a")মূল্যায়ন True"b".__eq__("a")মূল্যায়ন False

কোনও ফাংশনের রিটার্ন মান পরীক্ষা করার সময় আমি প্রথম দিকে এটি আবিষ্কার করেছিলাম, তবে দ্বিতীয় ক্ষেত্রে কোনও কিছুই ফেরত পাইনি - সুতরাং, ফাংশনটি ফিরে আসল None

এখানে কি হচ্ছে?

উত্তর:


178

এটি __dunder__প্রায়শই তাদের সমতুল্য অপারেটরগুলির জন্য উপযুক্ত প্রতিস্থাপন নয় বলে কেন পদ্ধতিগুলি সরাসরি ব্যবহার করা উচিত নয় এটির একটি দুর্দান্ত উদাহরণ ; ==সমতা তুলনা করার পরিবর্তে আপনার অপারেটরটি ব্যবহার করা উচিত , বা এই বিশেষ ক্ষেত্রে, যখন পরীক্ষা করা হয় তখন Noneব্যবহার করুন is(আরও তথ্যের জন্য উত্তরের নীচে যান)।

আপনি করেছেন

None.__eq__('a')
# NotImplemented

NotImplementedযেগুলি তুলনা করা হচ্ছে তার চেয়ে আলাদা যেগুলি ফেরত দেয়। অন্য একটি উদাহরণ বিবেচনা করুন যেখানে এই ফ্যাশনে বিভিন্ন ধরণের দুটি বস্তুর তুলনা করা হচ্ছে, যেমন 1এবং 'a'। এরকম (1).__eq__('a')আরো সঠিক নয়, এবং ফিরে আসবে NotImplemented। সমতা জন্য এই দুটি মান তুলনা করার সঠিক উপায় হবে

1 == 'a'
# False

এখানে কি হয়

  1. প্রথমে (1).__eq__('a')চেষ্টা করা হয়, যা ফিরে আসে NotImplemented। এটি নির্দেশ করে যে অপারেশন সমর্থিত নয়, তাই
  2. 'a'.__eq__(1)বলা হয়, যা একই একই প্রদান করে NotImplemented। সুতরাং,
  3. অবজেক্টগুলি এমনভাবে ব্যবহার করা হয় যেন সেগুলি এক নয় এবং Falseফিরে আসে।

এটি কীভাবে ঘটে তা চিত্রিত করার জন্য কিছু কাস্টম ক্লাস ব্যবহার করে একটি দুর্দান্ত ছোট্ট MCVE:

class A:
    def __eq__(self, other):
        print('A.__eq__')
        return NotImplemented

class B:
    def __eq__(self, other):
        print('B.__eq__')
        return NotImplemented

class C:
    def __eq__(self, other):
        print('C.__eq__')
        return True

a = A()
b = B()
c = C()

print(a == b)
# A.__eq__
# B.__eq__
# False

print(a == c)
# A.__eq__
# C.__eq__
# True

print(c == a)
# C.__eq__
# True

অবশ্যই, এটি ব্যাখ্যা করে না যে কেন অপারেশন সত্য হয়। এটি হ'ল NotImplementedপ্রকৃত সত্য মূল্য:

bool(None.__eq__("a"))
# True

একই রকম,

bool(NotImplemented)
# True

কোন মানগুলি সত্যবাদী এবং মিথ্যা বলে বিবেচিত হয় সে সম্পর্কে আরও তথ্যের জন্য, সত্যের মান পরীক্ষার উপর ডকস বিভাগটি দেখুন , পাশাপাশি এই উত্তরটিও দেখুন । এখানে যে মূল্য লক্ষ NotImplementedtruthy, কিন্তু এটা হয়েছে একটি ভিন্ন গল্প বর্গ একটি নির্ধারিত হত __bool__বা __len__পদ্ধতি যা ফিরে Falseবা 0যথাক্রমে।


আপনি যদি ==অপারেটরের ক্রিয়ামূলক সমতুল্য চান তবে ব্যবহার করুন operator.eq:

import operator
operator.eq(1, 'a')
# False

যাইহোক, পূর্বে উল্লিখিত হিসাবে, এই নির্দিষ্ট দৃশ্যের জন্য None, আপনি যেখানে পরীক্ষা করছেন সেখানে ব্যবহার করুন is:

var = 'a'
var is None
# False

var2 = None
var2 is None
# True

এর কার্যকরী সমতুল্য ব্যবহার করছে operator.is_:

operator.is_(var2, None)
# True

Noneএকটি বিশেষ অবজেক্ট এবং যে কোনও সময়ে মেমরিতে কেবলমাত্র 1 সংস্করণ বিদ্যমান। আইওডাব্লু, এটি NoneTypeক্লাসের একমাত্র সিঙ্গলটন (তবে একই বস্তুর অনেকগুলি রেফারেন্স থাকতে পারে)। PEP8 নির্দেশিকা এই স্পষ্ট করুন:

সিঙ্গেলনের মতো তুলনা Noneসর্বদা isবা is notসমতা অপারেটরগুলির সাথে করা উচিত ।

সংক্ষেপে বলা যায়, singletons পছন্দ None, সঙ্গে একটি রেফারেন্স চেক isআরো উপযুক্ত, যদিও উভয় ==এবং isঠিক সূক্ষ্ম কাজ করবে।


33

আপনি যে ফলাফলটি দেখছেন তা সেই কারণে ঘটে

None.__eq__("a") # evaluates to NotImplemented

মূল্যায়ন করে NotImplemented, এবং NotImplementedএর সত্য মানটি নথিভুক্ত হয় True:

https://docs.python.org/3/library/constants.html

বিশেষ মান যা বাইনারি বিশেষ পদ্ধতি দ্বারা ফিরিয়ে দিতে হবে (যেমন __eq__(), __lt__(), __add__(), __rsub__(), ইত্যাদি) নির্দেশ করে অপারেশন অন্য ধরনের সম্মান সঙ্গে বাস্তবায়িত হয়নি; ইন-জায়গা বাইনারি বিশেষ পদ্ধতি (যেমন দ্বারা ফিরে যেতে পারে __imul__(), __iand__()একই উদ্দেশ্যে, ইত্যাদি)। এর সত্য মান সত্য।

আপনি যদি __eq()__পদ্ধতিটি কেবল ব্যবহারের পরিবর্তে ম্যানুয়ালি কল করেন তবে আপনার ==ফিরে আসা সম্ভাবনা NotImplementedএবং এর সত্যতার মানটি সত্য তা মোকাবেলা করার জন্য আপনাকে প্রস্তুত থাকতে হবে ।


16

আপনি ইতিমধ্যে নির্ধারিত হিসাবে যদি আপনি এর মতো কিছু চেষ্টা করেন তবে None.__eq__("a")মূল্যায়ন করেNotImplemented

if NotImplemented:
    print("Yes")
else:
    print("No")

ফলাফল হলো

হ্যাঁ

এর অর্থ হল সত্যের মান NotImplemented true

এজন্য প্রশ্নের ফলাফল সুস্পষ্ট:

None.__eq__(something) উৎপাদনের NotImplemented

এবং bool(NotImplemented)সত্যকে মূল্যায়ন করে

তাই if None.__eq__("a")সর্বদা সত্য


1

কেন?

এটি একটি NotImplemented, হ্যাঁ:

>>> None.__eq__('a')
NotImplemented
>>> 

তবে আপনি যদি এটি দেখুন:

>>> bool(NotImplemented)
True
>>> 

NotImplementedপ্রকৃতপক্ষে সত্যবাদী মান, তাই সে কারণেই এটি ফিরে আসে b, যা কিছু হয় Trueতা পাস করবে, যা কিছুই Falseহবে না।

কীভাবে সমাধান করবেন?

এটি কিনা আপনার যাচাই করতে হবে True, তাই আরও সন্দেহজনক হোন, যেমন আপনি দেখুন:

>>> NotImplemented == True
False
>>> 

সুতরাং আপনি কি করবেন:

>>> if None.__eq__('a') == True:
    print('b')


>>> 

এবং আপনি দেখতে হিসাবে, এটি কিছুই ফেরত না।


1
সর্বাধিক দৃষ্টি আকর্ষণীয় উত্তর - v সার্থক সংযোজন - ধন্যবাদ
scharfmn

1
:) "সার্থক সংযোজন" আমি যা বলার চেষ্টা করছিলাম তা ক্যাপচার করে না (যেমন আপনি দেখুন) - সম্ভবত "বেল্টেড এক্সিলেন্স" আমি যা চেয়েছিলাম - চিয়ার্স
scharfmn

@scharfmn হ্যাঁ? আপনি এই উত্তরটি ইতিমধ্যে এর আগে কভার করেন নি যা যুক্ত করে তা সম্পর্কে আমি জানতে আগ্রহী।
cs95

কোনওভাবে এখানে ভিজ্যুয়াল / রিপ্লাই জিনিসগুলিতে স্পষ্টতা যুক্ত করুন - সম্পূর্ণ ডেমো
scharfmn

@scharfmn ... যা গৃহীত উত্তরগুলিও প্রম্পটগুলি সরিয়ে দেওয়া হয়েছে। টার্মিনাল প্রম্পটগুলি অলসভাবে রেখে দেওয়া হয়েছে বলে আপনি কি কেবল উচ্ছেদ করেছেন?
সিএস 95
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.