python - কেন 'যদি কেউ না.__ eq__("a") `সত্য'(কিন্তু মোটামুটি না) মূল্যায়ন বলে মনে হয়?




python-3.x string (3)

যদি আপনি Python 3.7 এ নিম্নলিখিত বিবৃতিটি কার্যকর করেন তবে এটি (আমার পরীক্ষায় থেকে) মুদ্রণ b :

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

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

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

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

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


কেন?

এটি একটি NotImplemented ফেরত, হ্যাঁ:

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

কিন্তু যদি আপনি এই দিকে তাকান:

>>> bool(NotImplemented)
True
>>> 

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

কিভাবে এটা সমাধান?

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

>>> NotImplemented == True
False
>>> 

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

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


>>> 

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


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

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

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

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

বাইনারি বিশেষ পদ্ধতিগুলি (যেমন __eq__() , __lt__() , __add__() , __rsub__() , ইত্যাদি) দ্বারা বিশেষ মূল্য ফেরত দেওয়া উচিত যা নির্দেশ করে যে অপারেশনটি অন্য ধরণের ক্ষেত্রে প্রয়োগ করা হয় না; একই উদ্দেশ্যে বাইনারি বিশেষ পদ্ধতিতে (যেমন __imul__() , __iand__() , ইত্যাদি) দ্বারা ফিরে আসতে পারে। তার সত্য মান সত্য।

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


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

আপনি করেছেন

None.__eq__('a')
# NotImplemented

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

1 == 'a'
# False

এখানে কি হয়

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

এখানে কী ঘটেছে তা বর্ণনা করার জন্য এখানে কিছু কাস্টম ক্লাস ব্যবহার করে একটি চমৎকার সামান্য এমসিভি রয়েছে:

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

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

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

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

যাইহোক, পূর্বে যেমন উল্লেখ করা হয়েছে, এই নির্দিষ্ট দৃশ্যের জন্য , যেখানে আপনি কোনটির জন্য চেক করছেন, ব্যবহার করুন:

var = 'a'
var is None
# False

var2 = None
var2 is None
# True

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

operator.is_(var2, None)
# True

None একটি বিশেষ বস্তু নয়, এবং স্মৃতিতে কেবলমাত্র 1 সংস্করণ বিদ্যমান থাকে। NoneType , এটি NoneType ক্লাসের একমাত্র NoneType (তবে একই বস্তুর কোনো উল্লেখ থাকতে পারে)। PEP8 নির্দেশিকা এই স্পষ্ট করে তোলে:

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

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





equivalence