`যদি`


95

আইডিয়াম এবং পাঠযোগ্যতা সম্পর্কে আমার একটি প্রশ্ন আছে এবং এই বিশেষ ক্ষেত্রে পাইথনের দর্শনগুলির সংঘাত আছে বলে মনে হচ্ছে:

আমি অভিধান বি থেকে অভিধান এ তৈরি করতে চাই বি তে যদি একটি নির্দিষ্ট কী উপস্থিত না থাকে তবে কিছুই করবেন না এবং চালিয়ে যান।

কোন উপায় ভাল?

try:
    A["blah"] = B["blah"]
except KeyError:
    pass

বা

if "blah" in B:
    A["blah"] = B["blah"]

"করুন এবং ক্ষমা প্রার্থনা করুন" বনাম "সরলতা এবং ব্যাখ্যা" itness

কোনটি ভাল এবং কেন?


4
দ্বিতীয় উদাহরণটি আরও ভাল হিসাবে লিখিত হতে পারে if "blah" in B.keys(), বা if B.has_key("blah")
girasquid

4
A.update(B)আপনার জন্য কাজ করে না?
সাইলেন্টগোস্ট

21
@ লুক: একটি ও (1) ক্রিয়াকলাপকে ও (এন) এর মধ্যে পরিবর্তিত করার has_keyপক্ষে inএবং চেক করার পক্ষে স্বীকৃত হয়েছে B.keys()
kindall

4
@ লুক: তা নয়। অবহিত .has_keyকরা হয়েছে এবং keysপাই 2 কে অনিবদ্ধ তালিকা তৈরি করে এবং পাই 3 কে অনর্থক
সাইলেন্টগোস্ট

4
'বিল্ড' এ, এ হিসাবে, এ শুরু করার জন্য খালি? এবং আমরা কেবল কিছু চাবি চাই? একটি ধী ব্যবহার করুন: A = dict((k, v) for (k, v) in B if we_want_to_include(k))
কার্ল নচেটেল

উত্তর:


77

ব্যতিক্রম শর্তসাপেক্ষ নয়।

শর্তসাপেক্ষ সংস্করণটি আরও পরিষ্কার। এটি প্রাকৃতিক: এটি সোজা প্রবাহ নিয়ন্ত্রণ, এটিই শর্তসাপেক্ষ, ব্যতিক্রম নয় for

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

সাধারণভাবে, আমি শর্তাধীন সংস্করণটি ডিফল্টরূপে দৃ strongly়ভাবে দৃic়ভাবে রাখার পরামর্শ দিচ্ছি যদি না আপনার নির্দিষ্ট কারণ না থাকে। শর্তসাপেক্ষ এটি করার সুস্পষ্ট উপায়, যা সাধারণত একটির অন্যের চেয়ে একটি সমাধান পছন্দ করার জন্য একটি দৃ recommend় সুপারিশ।


4
আমি রাজি নই। আপনি যদি বলেন "X করুন, এবং যদি এটি কাজ করে না, তবে Y করুন"। শর্তযুক্ত সমাধানের মূল কারণ এখানে, আপনাকে "blah"আরও প্রায়শই লিখতে হবে যা আরও ত্রুটি-প্রবণ পরিস্থিতির দিকে নিয়ে যায়।
glglgl

6
এবং, বিশেষত পাইথনে, ইএএফপি খুব ব্যাপকভাবে ব্যবহৃত হয়।
glglgl

8
পাইথন ব্যতীত আমি জানি যে কোনও ভাষার জন্য এই উত্তরটি সঠিক হবে।
টোমা জ্যাটো - মনিকা

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

তো, চূড়ান্ত রায় কী? :)
floatingpurr

62

তৃতীয় উপায়ও রয়েছে যা ব্যতিক্রম এবং ডাবল-লুক উভয়ই এড়িয়ে চলে, যা চেহারা ব্যয়বহুল হলে গুরুত্বপূর্ণ হতে পারে:

value = B.get("blah", None)
if value is not None: 
    A["blah"] = value

যদি আপনি অভিধান রয়েছে বলে আশা Noneমূল্যবোধ, তোমার মত আরো কিছু গূঢ় ধ্রুবক ব্যবহার করতে পারেন NotImplemented, Ellipsisঅথবা একটি নতুন করুন:

MyConst = object()
def update_key(A, B, key):
    value = B.get(key, MyConst)
    if value is not MyConst: 
        A[key] = value

যাইহোক, ব্যবহার update()করা আমার পক্ষে সবচেয়ে পঠনযোগ্য বিকল্প:

a.update((k, b[k]) for k in ("foo", "bar", "blah") if k in b)

14

আমি যা বুঝি সেগুলি থেকে আপনি ডোক এ থেকে কী, মান জোড়া দিয়ে ডিক এ আপডেট করতে চান

update একটি ভাল পছন্দ।

A.update(B)

উদাহরণ:

>>> A = {'a':1, 'b': 2, 'c':3}
>>> B = {'d': 2, 'b':5, 'c': 4}
>>> A.update(B)
>>> A
{'a': 1, 'c': 4, 'b': 5, 'd': 2}
>>> 

"যদি বি তে একটি নির্দিষ্ট কী উপস্থিত না থাকে" দুঃখিত, আরও স্পষ্ট হওয়া উচিত ছিল, তবে আমি কেবলমাত্র মানগুলিতে অনুলিপি করতে চাই যদি বিতে নির্দিষ্ট কীগুলি বিদ্যমান থাকে। সমস্ত বি তে নয়
লিমোবাইল

4
@ লাইমোবাইল -A.update({k: v for k, v in B.iteritems() if k in specificset})
সর্বনিম্ন

8

পাইথন সম্পাদনা উইকি থেকে সরাসরি উদ্ধৃতি:

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

সুতরাং মনে হচ্ছে পরিস্থিতি অনুসারে উভয় বিকল্পই কার্যকর able আরও বিশদের জন্য আপনি এই লিঙ্কটি চেক করতে পছন্দ করতে পারেন: চেষ্টা-ছাড়া-কর্মক্ষমতা


এটি একটি আকর্ষণীয় পড়া, তবে আমি কিছুটা অসম্পূর্ণ মনে করি। ব্যবহৃত
ডিকটির

3

আমি মনে করি যে এখানে সাধারণ নিয়মটি A["blah"]সাধারণত উপস্থিত থাকবে, যদি চেষ্টা না করা ব্যতীত ভাল হয় তবে ব্যবহার না করেif "blah" in b:

আমি মনে করি "চেষ্টা" সময় সাপেক্ষ তবে "ব্যতীত" বেশি ব্যয়বহুল।


10
ডিফল্টরূপে অপ্টিমাইজেশনের দৃষ্টিকোণ থেকে কোডের কাছে যাবেন না; এটি একটি পাঠযোগ্যতা এবং রক্ষণাবেক্ষণের দৃষ্টিভঙ্গি থেকে যোগাযোগ করুন। লক্ষ্যটি সুনির্দিষ্টভাবে অপ্টিমাইজেশন না করা পর্যন্ত এটিই ভুল মানদণ্ড (এবং যদি এটি অপটিমাইজেশন হয় তবে উত্তরটি মানদণ্ড নয়, অনুমান করা নয়)।
গ্লেন মেইনার্ড

আমার সম্ভবত শেষ পয়েন্টটি বন্ধনী বা কোনওভাবে ভুগুয়ারে রাখা উচিত ছিল - আমার মূল পয়েন্টটি প্রথমটি ছিল এবং আমার মনে হয় এটির দ্বিতীয়টির অতিরিক্ত সুবিধা রয়েছে।
নীল

3

আমি মনে করি দ্বিতীয় কোডটি হ'ল যদি আপনার কোডটি অনুধাবন না করা উচিত তবে তা যা উচিত:

try:
    A["foo"] = B["foo"]
    A["bar"] = B["bar"]
    A["baz"] = B["baz"]
except KeyError:
    pass

মনে রাখবেন যে কোনও কী নেই যা না হলেই কোডটি বাতিল হয়ে যাবে B। যদি এই কোডটি বোঝায়, তবে আপনার ব্যতিক্রম পদ্ধতিটি ব্যবহার করা উচিত, অন্যথায় পরীক্ষার পদ্ধতিটি ব্যবহার করুন। আমার মতে, এটি সংক্ষিপ্ত এবং স্পষ্টভাবে অভিপ্রায় প্রকাশ করেছে, ব্যতিক্রম পদ্ধতির চেয়ে এটি পড়া সহজ easier

অবশ্যই, আপনাকে ব্যবহার updateকরতে বলছে এমন লোকেরা সঠিক। আপনি যদি পাইথনের এমন কোনও সংস্করণ ব্যবহার করছেন যা অভিধান বোঝার সমর্থন করে তবে আমি এই কোডটি দৃ strongly়ভাবে পছন্দ করব:

updateset = {'foo', 'bar', 'baz'}
A.update({k: B[k] for k in updateset if k in B})

"মনে রাখবেন যে বি তে নেই এমন কোনও কী উপস্থিত হওয়ার সাথে সাথে কোডটি বাতিল হয়ে যাবে" " - এ কারণেই চেষ্টাটি কেবল সর্বনিম্ন সর্বনিম্ন রাখাই ভাল অনুশীলন: ব্লক, সাধারণত এটি একটি একক লাইন। প্রথম উদাহরণটি একটি লুপের অংশ হিসাবে আরও ভাল হতে পারেfor key in ["foo", "bar", "baz"]: try: A[key] = B[key]
জিম

2

অন্যান্য ভাষাগুলির নিয়মটি ব্যতিক্রমী অবস্থার জন্য ব্যতিক্রমগুলি সংরক্ষণ করা, অর্থাৎ নিয়মিত ব্যবহারে ঘটে না এমন ত্রুটি। কীভাবে সেই নিয়মটি পাইথনের ক্ষেত্রে প্রযোজ্য তা জানেন না, কারণ এই বিধি দ্বারা স্টপ ইন্টেরেশনটি থাকা উচিত নয়।


আমি মনে করি এই বুকে বাদাম এমন ভাষা থেকে উদ্ভূত হয়েছে যেখানে ব্যতিক্রম হ্যান্ডলিং ব্যয়বহুল এবং তাই পারফরম্যান্সে উল্লেখযোগ্য প্রভাব ফেলতে পারে। আমি এর পিছনে কোন সত্যিকারের ন্যায়সঙ্গততা বা যুক্তি দেখিনি।
জন লা রুই

@ জনলআরউই না, পারফরম্যান্স আসলে কারণ নয়। ব্যতিক্রমগুলি হ'ল এক প্রকার অ-স্থানীয় গোটো , যা কিছু লোক কোডের পঠনযোগ্যতাকে বাধা হিসাবে বিবেচনা করে। যাইহোক, এইভাবে ব্যাতিক্রমের ব্যবহার পাইথনে আইডিয়োমেটিক হিসাবে বিবেচিত হয় সুতরাং উপরেরটি প্রয়োগ হয় না।
আয়ান গোল্ডবাই

শর্তসাপেক্ষ রিটার্নগুলিও "অ-স্থানীয় গোতো" এবং অনেক লোক কোড ব্লকের শেষে সেন্ডিনেলগুলি পরিদর্শন করার পরিবর্তে সেই স্টাইলটি পছন্দ করে।
কাওবার্ট

1

ব্যক্তিগতভাবে, আমি দ্বিতীয় পদ্ধতির দিকে ঝুঁকছি (তবে ব্যবহার করছি has_key):

if B.has_key("blah"):
  A["blah"] = B["blah"]

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

এটি দেখা যাচ্ছে (আপনার প্রশ্নের মন্তব্য দেখুন), has_keyঅবহেলিত - সুতরাং আমি অনুমান করি যে এটি আরও ভাল লিখেছেন

if "blah" in B:
  A["blah"] = B["blah"]

1

শুরু Python 3.8, এবং অ্যাসাইনমেন্ট এক্সপ্রেশন (পিইপি 572) ( :=অপারেটর) এর পরিচিতি , আমরা শর্ত মানটি dictB.get('hello', None)একটি চলকতে ক্যাপচার করতে পারি valueযাতে এটি না হয় None( উভয়টি dict.get('hello', None)সম্পর্কিত মান হিসাবে প্রত্যাবর্তন হিসাবে None) যাচাই করতে পারে এবং তারপরে এটি ব্যবহার করতে পারি শর্ত:

# dictB = {'hello': 5, 'world': 42}
# dictA = {}
if value := dictB.get('hello', None):
  dictA["hello"] = value
# dictA is now {'hello': 5}

4
মানটি == 0
এরিক

0

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

অনুমতি চেয়ে ক্ষমা চাইতে সহজ। (ইএএফপি)

পাইথন ডক্স রেফারেন্সটি এখানে দেখুন

এছাড়াও, ব্রেটের এই ব্লগ , অন্যতম মূল দেব, সংক্ষেপে এগুলির বেশিরভাগ স্পর্শ করে।

এখানে অন্য এসও আলোচনা দেখুন :

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