কেন `a == b বা c বা d` সর্বদা সত্যের কাছে মূল্যায়ন করে?


108

আমি এমন একটি সুরক্ষা ব্যবস্থা লিখছি যা অননুমোদিত ব্যবহারকারীদের অ্যাক্সেসকে অস্বীকার করে।

import sys

print("Hello. Please enter your name:")
name = sys.stdin.readline().strip()
if name == "Kevin" or "Jon" or "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

এটি প্রত্যাশিত হিসাবে অনুমোদিত ব্যবহারকারীদের অ্যাক্সেসকে মঞ্জুরি দেয়, তবে এটি অননুমোদিত ব্যবহারকারীদেরও দেয়!

Hello. Please enter your name:
Bob
Access granted.

কেন এমন হয়? আমি nameকেভিন, জোন বা ইনবারের সমান হলে কেবল অ্যাক্সেসের মঞ্জুরি দিতে স্পষ্টভাবে বলেছি । আমি বিপরীত যুক্তিও চেষ্টা করেছি if "Kevin" or "Jon" or "Inbar" == name, তবে ফলাফলটি একই।


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

মার্টিজান উত্তরটি "প্রাকৃতিক ভাষা ব্যবহার করবেন না" দিয়ে এটির ব্যাখ্যাটি কেবল দুর্দান্ত, অন্যরা, ভাল, ... এগুলি গৌরবময় উজ্জ্বল সময় ছিল ... নীচের উত্তরগুলি কেবল এটি পুনরুক্ত করে। আমার জন্য এটি একটি সদৃশ। তবে মার্টিজন যদি আবার খুলতে চান, ভাল, আমার আপত্তি নেই।
জিন-ফ্রান্সোইস ফ্যাব্রে

4
এই সমস্যার প্রকারভেদ অন্তর্ভুক্ত x or y in z, x and y in z, x != y and zঅন্য কয়েকজন এবং। যদিও এই প্রশ্নের সাথে একেবারে অভিন্ন নয়, মূল কারণ তাদের সবার জন্য একই। কেবল এটিই উল্লেখ করতে চেয়েছিলাম যে কেউ যদি তাদের প্রশ্নটিকে এর সদৃশ হিসাবে বন্ধ করে দেয় এবং নিশ্চিত হয় না যে এটি কীভাবে প্রাসঙ্গিক।
অরণ-ফে

উত্তর:


151

অনেক ক্ষেত্রে পাইথন প্রাকৃতিক ইংরাজির মতো দেখায় এবং আচরণ করে তবে এটি এমন একটি ক্ষেত্রে যেখানে বিমূর্ততা ব্যর্থ হয়। লোকেরা "জোন" এবং "ইনবার" ক্রিয়া "সমান" ক্রিয়াতে যুক্ত হওয়া বস্তুগুলি নির্ধারণের জন্য প্রসঙ্গের ক্লু ব্যবহার করতে পারে তবে পাইথন ইন্টারপ্রেটার আরও আক্ষরিক মনের অধিকারী।

if name == "Kevin" or "Jon" or "Inbar":

যৌক্তিকভাবে এর সমতুল্য:

if (name == "Kevin") or ("Jon") or ("Inbar"):

যা ব্যবহারকারী বব এর জন্য সমান:

if (False) or ("Jon") or ("Inbar"):

orঅপারেটর একটি ইতিবাচক প্রথম যুক্তি বেছে সত্য মান :

if ("Jon"):

এবং যেহেতু "জন" এর ইতিবাচক সত্য মান রয়েছে তাই ifব্লকটি কার্যকর করে। এ কারণেই প্রদত্ত নাম নির্বিশেষে "অ্যাক্সেস মঞ্জুরিপ্রাপ্ত" মুদ্রিত হয়।

এই সমস্ত যুক্তি প্রকাশের ক্ষেত্রেও প্রযোজ্য if "Kevin" or "Jon" or "Inbar" == name। প্রথম মান,, "Kevin"সত্য, তাই ifব্লকটি কার্যকর করে।


এই শর্তসাপেক্ষে সঠিকভাবে নির্মাণের দুটি সাধারণ উপায় রয়েছে are

  1. ==একেকটি অপারেটরকে প্রতিটি মানের সাথে সুস্পষ্টভাবে পরীক্ষা করতে ব্যবহার করুন :
    if name == "Kevin" or name == "Jon" or name == "Inbar":

  2. বৈধ মানগুলির ক্রম রচনা করুন, এবং inসদস্যতার জন্য পরীক্ষার জন্য অপারেটরটি ব্যবহার করুন :
    if name in {"Kevin", "Jon", "Inbar"}:

দু'জনের মধ্যে সাধারণত দ্বিতীয়টি পছন্দ করা উচিত কারণ এটি পড়া সহজ এবং দ্রুতও:

>>> import timeit
>>> timeit.timeit('name == "Kevin" or name == "Jon" or name == "Inbar"', setup="name='Inbar'")
0.4247764749999945
>>> timeit.timeit('name in {"Kevin", "Jon", "Inbar"}', setup="name='Inbar'")
0.18493307199999265

যারা প্রমাণ পেতে পারেন তাদের পক্ষে if a == b or c or d or e: ...এটি অবশ্যই এইভাবে বিশ্লেষণ করা হয়েছে। অন্তর্নির্মিত astমডিউল একটি উত্তর সরবরাহ করে:

>>> import ast
>>> ast.parse("if a == b or c or d or e: ...")
<_ast.Module object at 0x1031ae6a0>
>>> ast.dump(_)
"Module(body=[If(test=BoolOp(op=Or(), values=[Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), Name(id='c', ctx=Load()), Name(id='d', ctx=Load()), Name(id='e', ctx=Load())]), body=[Expr(value=Ellipsis())], orelse=[])])"
>>>

সুতরাং testএর ifভালো বিবৃতি দেখায়:

BoolOp(
 op=Or(),
 values=[
  Compare(
   left=Name(id='a', ctx=Load()),
   ops=[Eq()],
   comparators=[Name(id='b', ctx=Load())]
  ),
  Name(id='c', ctx=Load()),
  Name(id='d', ctx=Load()),
  Name(id='e', ctx=Load())
 ]
)

এক দেখতে পারেন, এটা বুলিয়ান অপারেটর এর orএকাধিক প্রয়োগ values, যথা, a == bএবং c, dএবং e


("Kevin", "Jon", "Inbar")সেটের পরিবর্তে টিপল বেছে নেওয়ার কোনও নির্দিষ্ট কারণ আছে কি {"Kevin", "Jon", "Inbar"} ?
মানব

2
সত্যই নয়, যেহেতু উভয়ই কাজ করে যদি মানগুলি সমস্ত হ্যাশযোগ্য হয়। টিপল সদস্যপদ পরীক্ষার চেয়ে সেট সদস্যপদ পরীক্ষার আরও ভাল-ও জটিলতা রয়েছে তবে টিউপল তৈরির চেয়ে সেট তৈরি করা কিছুটা ব্যয়বহুল। আমি মনে করি এটি এর মতো ছোট সংগ্রহগুলির জন্য বেশিরভাগ ধোয়া। সময়সীমার সাথে ঘুরে বেড়ানো আমার মেশিনের a in {b, c, d}চেয়ে দ্বিগুণ দ্রুত a in (b, c, d)। এটি কোডের পারফরম্যান্স-সমালোচনামূলক অংশ কিনা তা নিয়ে ভাবতে হবে।
কেভিন

3
'ইন' ব্যবহার করার সময় টিপল বা তালিকান 'যদি' ক্লজ? সদস্যপদ পরীক্ষার জন্য সেট আক্ষরিক প্রস্তাব দেয়। আমি আমার পোস্ট আপডেট করব।
কেভিন

আধুনিক পাইথনগুলিতে, এটি সনাক্ত করে যে সেটটি একটি ধ্রুবক এবং frozensetপরিবর্তে এটি করে তোলে , তাই নির্ধারিত সেট ওভারহেড সেখানে নেই। dis.dis(compile("1 in {1, 2, 3}", '<stdin>', 'eval'))
এন্ডোলিথ

1

সাধারণ প্রকৌশল সমস্যা, আসুন এটি আরও কিছুটা এগিয়ে।

In [1]: a,b,c,d=1,2,3,4
In [2]: a==b
Out[2]: False

কিন্তু, সি ভাষা থেকে উত্তরাধিকার সূত্রে পাইথন একটি শূন্য নয় পূর্ণসংখ্যার যৌক্তিক মানটিকে সত্য হিসাবে মূল্যায়ন করে।

In [11]: if 3:
    ...:     print ("yey")
    ...:
yey

পাইথন এখন সেই যুক্তি তৈরি করে এবং আপনাকে যুক্তিযুক্ত আক্ষরিক যেমন বা পূর্ণসংখ্যার উপর ব্যবহার করতে দেয় এবং তাই

In [9]: False or 3
Out[9]: 3

পরিশেষে

In [4]: a==b or c or d
Out[4]: 3

এটি লেখার উপযুক্ত উপায় হ'ল:

In [13]: if a in (b,c,d):
    ...:     print('Access granted')

সুরক্ষার জন্য আমি আপনাকে হার্ড কোডের পাসওয়ার্ড না দেওয়ার পরামর্শ দিই।


1

3 টি শর্ত চেক ইন আছে if name == "Kevin" or "Jon" or "Inbar":

  • নাম == "কেভিন"
  • "জন"
  • "Inbar"

এবং এটি যদি বিবৃতি সমতুল্য হয়

if name == "Kevin":
    print("Access granted.")
elif "Jon":
    print("Access granted.")
elif "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

যেহেতু elif "Jon"সর্বদা সত্য হবে তাই যে কোনও ব্যবহারকারীর অ্যাক্সেস মঞ্জুর

সমাধান


আপনি নীচের যে কোনও একটি পদ্ধতি ব্যবহার করতে পারেন

দ্রুত

if name in ["Kevin", "Jon", "Inbar"]:
    print("Access granted.")
else:
    print("Access denied.")

ধীরে

if name == "Kevin" or name == "Jon" or name == "Inbar":
    print("Access granted.")
else:
    print("Access denied.")

ধীর + অপ্রয়োজনীয় কোড

if name == "Kevin":
    print("Access granted.")
elif name == "Jon":
    print("Access granted.")
elif name == "Inbar":
    print("Access granted.")
else:
    print("Access denied.")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.