পাইথোনিক উপায় "যদি এক্স: রিটার্ন এক্স" বিবৃতি এড়ানো যায়


218

আমার কাছে এমন একটি পদ্ধতি রয়েছে যা নির্দিষ্ট অবস্থার জন্য পরীক্ষা করার জন্য ক্রমানুসারে 4 টি অন্যান্য পদ্ধতিতে কল করে এবং যখনই কেউ সত্যবাদী কিছু ফিরিয়ে দেয় তখনই তাৎক্ষণিকভাবে (নিম্নলিখিতগুলি পরীক্ষা করে না) ফিরে আসে।

def check_all_conditions():
    x = check_size()
    if x:
        return x

    x = check_color()
    if x:
        return x

    x = check_tone()
    if x:
        return x

    x = check_flavor()
    if x:
        return x
    return None

এটি অনেকটা ব্যাগেজ কোডের মতো মনে হচ্ছে। বিবৃতি প্রতি 2-লাইন পরিবর্তে, আমি বরং কিছু করতে চাই:

x and return x

তবে এটি পাইথন অবৈধ। আমি কি এখানে একটি সহজ, মার্জিত সমাধান মিস করছি? ঘটনাচক্রে, এই পরিস্থিতিতে, এই চারটি চেক পদ্ধতি ব্যয়বহুল হতে পারে, তাই আমি তাদের একাধিকবার কল করতে চাই না।


7
এই এক্স এর কি? এগুলি কি শুধুই সত্য / মিথ্যা, বা কোনও তথ্য সমন্বিত ডেটা স্ট্রাকচারগুলি, কোনও বা অকার্যকর কোনও ডেটার অনুপস্থিতি নির্দেশ করার জন্য বিশেষ কেস হিসাবে ব্যবহৃত হচ্ছে? যদি এটি পরে থাকে তবে এর পরিবর্তে আপনার অবশ্যই ব্যতিক্রমগুলি ব্যবহার করা উচিত।
নাথানিয়েল

13
@gerrit উপরে উপস্থাপিত কোডটি অনুমান / সিউডো কোড যা কোড পর্যালোচনার বাইরে বিষয়বস্তু। পোস্টের লেখক যদি তাদের আসল, প্রকৃত ওয়ার্কিং কোডটি পর্যালোচনা করতে চান তবে হ্যাঁ তারা কোড পর্যালোচনাতে পোস্ট করতে স্বাগত।
ফ্রেঞ্চিস

4
কেন আপনি x and return xতার চেয়ে ভাল মনে করেন if x: return x? পরেরটি আরও বেশি পঠনযোগ্য এবং এভাবে বজায় রাখা যায়। চরিত্র বা রেখার সংখ্যা সম্পর্কে আপনার খুব বেশি চিন্তা করা উচিত নয়; পঠনযোগ্যতা গণনা। এগুলি যাইহোক যাইহোক হোয়াইটস্পেস অক্ষরগুলির ঠিক একই সংখ্যা এবং যদি আপনার সত্যিই অবশ্যই করা if x: return xহয় তবে কেবল একটি লাইনে কাজ করবে।
মার্সেলম

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

7
@ jpmc26 ওপি স্পষ্টত সত্যবাদী প্রত্যাবর্তন মূল্যের কথা বলে, এবং তার কোডটি ফিরে আসে x(এর বিপরীতে bool(x)) সুতরাং আমি মনে করি এটি নিরাপদ যে এই ধারণাটি নেওয়া নিরাপদ যে ওপির কার্যগুলি যে কোনও কিছু ফিরিয়ে দিতে পারে, এবং তিনি সত্যবাদী যেটি প্রথম চান তা চান।
টিমজেব

উত্তর:


278

আপনি একটি লুপ ব্যবহার করতে পারেন:

conditions = (check_size, check_color, check_tone, check_flavor)
for condition in conditions:
    result = condition()
    if result:
        return result

এটির সাথে যুক্ত হওয়া সুবিধা রয়েছে যে আপনি এখন কন্ডিশনের সংখ্যা পরিবর্তনশীল করতে পারবেন।

আপনি ব্যবহার করতে পারে map()+ + filter()(পাইথন 3 সংস্করণ ব্যবহার future_builtinsসংস্করণ পাইথন 2) প্রথম ম্যাচিং মান পেতে:

try:
    # Python 2
    from future_builtins import map, filter
except ImportError:
    # Python 3
    pass

conditions = (check_size, check_color, check_tone, check_flavor)
return next(filter(None, map(lambda f: f(), conditions)), None)

তবে এটি যদি আরও পাঠযোগ্য হয় তবে বিতর্কযোগ্য।

আর একটি বিকল্প জেনারেটর এক্সপ্রেশন ব্যবহার করা হয়:

conditions = (check_size, check_color, check_tone, check_flavor)
checks = (condition() for condition in conditions)
return next((check for check in checks if check), None)

27
যদি শর্তগুলি সত্যিই কেবল শর্ত হয়, তবে বুুলিয়ানস তবে আপনার প্রথম প্রস্তাবনায় আপনি anyলুপের পরিবর্তে বিল্টিনও ব্যবহার করতে পারেন । return any(condition() for condition in conditions)

4
@ লিওনহার্ড: anyভিতরে প্রায় একই বাস্তবায়ন রয়েছে। তবে এটি দেখতে আরও ভাল দেখাচ্ছে, দয়া করে এটি একটি উত্তর হিসাবে পোস্ট করুন)
নিক ভলিনকিন

13
পঠনযোগ্যতা প্রায় সমস্ত অন্যান্য বিবেচনা ট্রাম্প। আপনি বলছেন, মানচিত্র / ফিল্টারটি 'বিতর্কযোগ্য', আমি আমার ভোটটি নিঃসন্দেহে কুৎসিত জন্য রেখেছি। ধন্যবাদ, অবশ্যই, তবে আমার দলের কেউ যদি এই কোডটির জন্য কোনও মানচিত্র / ফিল্টার রাখেন আমি এগুলি অন্য দলে স্থানান্তর করব বা তাদের বেডপ্যান ডিউটিতে নিযুক্ত করব।
কেভিন জে রাইস

15
কোডের এই অপঠনযোগ্য ব্লকটি কি আসলেই "পাইথোনিয়ান"? এবং বিশেষত জিপিংয়ের ধারণা conditionsএবং arguments? এটি আইএমএইচও মূল কোডের চেয়ে অনেক খারাপ, যা আমার ব্রেইন পার্সারকে পার্স করতে প্রায় 10 সেকেন্ড সময় নেয়।
yo '

34
"পাইথন পছন্দ করুন", তারা বলেছিল। "পার্ল অপঠনযোগ্য", তারা বলেছিল। এবং তারপর এই ঘটেছে: return next((check for check in checks if check), None)
jja

393

বিকল্প হিসাবে মার্তিজানের জবাব, আপনি চেইন করতে পারেন or। এটি প্রথম সত্যবাদী মানটি ফিরিয়ে দেবে, বা Noneসত্যের কোনও মান না থাকলে:

def check_all_conditions():
    return check_size() or check_color() or check_tone() or check_flavor() or None

ডেমো:

>>> x = [] or 0 or {} or -1 or None
>>> x
-1
>>> x = [] or 0 or {} or '' or None
>>> x is None
True

9
অবশ্যই, তবে যদি কয়েকটি বিকল্পের বেশি থাকে তবে এটি দ্রুত পড়তে ক্লান্তিকর হবে। প্লাস আমার পদ্ধতির সাহায্যে আপনাকে পরিবর্তনশীল সংখ্যক শর্তাদি ব্যবহার করতে দেওয়া হয়।
Martijn Pieters

14
@ মার্তিজজনপিটার আপনি \প্রতিটি চেকটিকে তার নিজস্ব লাইনে রাখতে ব্যবহার করতে পারেন ।
ক্যারিডর্ক

12
@ মার্তিজন পিটারস আমি কখনই বুঝিয়েছি আমার উত্তরটি আপনার চেয়ে উত্তম, আমিও আপনার উত্তরটি পছন্দ করি :)
টাইমজব

38
@ ক্যারিডরক: \লজিকাল লাইনটি প্রসারিত করতে আমি দৃ strongly়ভাবে অপছন্দ করি । পরিবর্তে যেখানে সম্ভব প্রথম বন্ধনী ব্যবহার করুন; যাতে return (....)নতুন লাইনগুলি প্রয়োজন মতো .োকানো হয়। তবুও, এটি এক দীর্ঘ যৌক্তিক লাইন হবে।
মার্টিজন পিটারস

47
আমি মনে করি এটিই আরও ভাল সমাধান। "যদি কয়েকটি বিকল্পের চেয়ে বেশি বিকল্প থাকে তবে এটি ক্লান্তিকর হয়ে উঠবে [..]" যুক্তিটি হ'ল, কারণ একটি একক ক্রিয়াকলাপ যাইহোক, অতিরিক্ত সংখ্যক চেক করা উচিত নয়। যদি এটি প্রয়োজন হয়, চেকগুলি একাধিক ফাংশনে বিভক্ত করা উচিত।
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

88

এটি পরিবর্তন করবেন না

বিভিন্ন অন্যান্য উত্তর শো হিসাবে এটি করার অন্যান্য উপায় রয়েছে। কোনওটিই আপনার মূল কোডের মতো পরিষ্কার নয়।


39
আমি এর বিরুদ্ধে তর্ক করব, তবে আপনার পরামর্শটি বৈধ হওয়া উচিত। ব্যক্তিগতভাবে, আমি আমার চোখের ওপি পড়ার চেষ্টা করতে গিয়ে স্ট্রেস দেখতে পাই, উদাহরণস্বরূপ, টিম্বেজের সমাধানটি তাত্ক্ষণিকভাবে ক্লিক করে।
রিটি 43

3
এটা সত্যিই মতামত একটি বিষয়। আমার ব্যক্তিগতভাবে, আমি পরে নিউলাইনগুলি সরিয়ে ফেলব :, কারণ আমি if x: return xবেশ সূক্ষ্ম বলে মনে করি এবং এটি ফাংশনটিকে আরও কমপ্যাক্ট দেখায়। তবে তা কেবল আমার হতে পারে।
yo '

2
এটা শুধু আপনি না। orটাইমেজ হিসাবে করা ব্যবহার করা একটি যথাযথ এবং সুস্পষ্ট বুদ্ধিমাধ্যম। অনেক ভাষায় এ রয়েছে; সম্ভবত যখন এটি বলা হয় তখন এটি orelseআরও স্পষ্ট হয়, তবে এমনকি সরল পুরাতন or(বা ||অন্যান্য ভাষায়) বোঝাতে বোঝানো হয় প্রথমটি যদি "কাজ না করে" তবে চেষ্টা করার বিকল্প হিসাবে বোঝা যায়।
রায় তোয়াল

1
@ রায়টোল: অন্য ভাষা থেকে আইডিয়ামগুলি আমদানি করা কোডকে অবলম্বন করার এক দুর্দান্ত উপায়।
জ্যাক এইডলি

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

83

কার্যকরভাবে টাইম্বের মতো একই উত্তর, তবে আপনি ভাল ফর্ম্যাটিংয়ের জন্য প্রথম বন্ধনী ব্যবহার করতে পারেন:

def check_all_the_things():
    return (
        one()
        or two()
        or five()
        or three()
        or None
    )

8
প্রত্যেকে দয়া করে এই উত্তরটি প্রথম স্থান পর্যন্ত বাড়িয়ে তুলতে সহায়তা করুন। আপনার অংশ না!
জিওম

74

কার্লির আইন অনুসারে , আপনি দুটি উদ্বেগ বিভক্ত করে এই কোডটি আরও পঠনযোগ্য করতে পারেন:

  • আমি কি জিনিস পরীক্ষা করতে পারি?
  • একটি জিনিস সত্য ফিরে এসেছে?

দুটি ফাংশন মধ্যে:

def all_conditions():
    yield check_size()
    yield check_color()
    yield check_tone()
    yield check_flavor()

def check_all_conditions():
    for condition in all_conditions():
        if condition:
            return condition
    return None

এটি এড়ানো:

  • জটিল যৌক্তিক কাঠামো
  • সত্যিই দীর্ঘ লাইন
  • পুনরাবৃত্তি

... রৈখিক সংরক্ষণের সময়, সহজেই প্রবাহের পড়া।

আপনার নির্দিষ্ট পরিস্থিতিতে আপনি সম্ভবত আরও ভাল ফাংশন নাম নিয়ে আসতে পারেন যা এটিকে আরও পাঠযোগ্য করে তোলে।


আমি এটি পছন্দ করি, যদিও সত্য / মিথ্যাটিকে শর্তে পরিবর্তন করা উচিত / প্রশ্নের সাথে মেলে না None
ম্যালকম

2
এটি আমার প্রিয়! এটি বিভিন্ন চেক এবং যুক্তিগুলির সাথে কপি করে cop বেশিরভাগ ক্ষেত্রে সম্ভবত এই নির্দিষ্ট উদাহরণের জন্য অতিরিক্ত ছাড় দেওয়া হয়েছে তবে ভবিষ্যতের সমস্যার জন্য সত্যিকারের উপকারী একটি সরঞ্জাম!
rjh

4
নোটটি return Noneপ্রয়োজনীয় নয়, কারণ ফাংশনগুলি Noneডিফল্টরূপে ফিরে আসে । তবে Noneসুস্পষ্টভাবে ফিরে আসার মতো কোনও সমস্যা নেই এবং আমি পছন্দ করি যে আপনি এটি করতে পছন্দ করেছেন।
টাইমজব

1
আমি মনে করি একটি স্থানীয় ফাংশন সংজ্ঞা দিয়ে এই পদ্ধতির আরও ভালভাবে প্রয়োগ করা হবে।
জ্যাক এইডলি

1
@ টিমজেব "স্পষ্ট বর্ণিত থেকে উত্তম," পাইথনের জেন
jpmc26

42

এটি মার্টিজেন্সের প্রথম উদাহরণের একটি বৈকল্পিক। এটি সংক্ষিপ্ত-প্রচারের অনুমতি দেওয়ার জন্য "কলযোগ্যদের সংগ্রহ"-স্টাইলও ব্যবহার করে।

লুপের পরিবর্তে আপনি বিল্টিন ব্যবহার করতে পারেন any

conditions = (check_size, check_color, check_tone, check_flavor)
return any(condition() for condition in conditions) 

নোট করুন যে anyএকটি বুলিয়ান দেয়, সুতরাং আপনার যদি চেকটির সঠিক রিটার্ন মান প্রয়োজন হয় তবে এই সমাধানটি কার্যকর হবে না। anyমধ্যে পার্থক্য করা হবে না 14, 'red', 'sharp', 'spicy'রিটার্ন মান হিসাবে, সব তারা যেমন ফেরত পাঠানো হবে True


আপনি next(itertools.ifilter(None, (c() for c in conditions)))বুলিয়ান এ ingালাই না করে আসল মান পেতে পারেন।
কোজিরো

1
anyআসলে কি শর্ট সার্কিট হয়?
zwol

1
@zwol হ্যাঁ কিছু নমুনা ফাংশন দিয়ে এটি ব্যবহার করে দেখুন বা docs.python.org/3/library/funitions.html

1
এটি 'বা' দিয়ে 4 টি ফাংশন শৃঙ্খলাবদ্ধ হওয়ার চেয়ে কম পঠনযোগ্য এবং শর্তগুলির সংখ্যা বড় বা গতিশীল হলে কেবল অর্থ প্রদান করে।
rjh

1
@rjh এটি পুরোপুরি পাঠযোগ্য; এটি কেবল একটি তালিকা আক্ষরিক এবং একটি উপলব্ধি। আমি এটিকে পছন্দ করব কারণ আমার চোখের তৃতীয় প্রায় পরে তাকিয়ে আছেx = bar(); if x: return x;
ব্ল্যাকলাইট শাইনিং

27

আপনি কি কেবল if x: return xএক লাইনে সমস্ত লেখার কথা বিবেচনা করেছেন ?

def check_all_conditions():
    x = check_size()
    if x: return x

    x = check_color()
    if x: return x

    x = check_tone()
    if x: return x

    x = check_flavor()
    if x: return x

    return None

এটি আপনার যা যা ছিল তার চেয়ে কম পুনরাবৃত্তিযোগ্য নয় , তবে IMNSHO এটি বেশ কিছুটা মসৃণ পড়ে reads


24

আমি বেশ অবাক হয়েছি কেউ anyএই উদ্দেশ্যে নির্মিত যা বিল্ট ইন উল্লেখ করেনি :

def check_all_conditions():
    return any([
        check_size(),
        check_color(),
        check_tone(),
        check_flavor()
    ])

মনে রাখবেন যে এই বাস্তবায়নটি সম্ভবত সবচেয়ে পরিষ্কার, এটি প্রথমটি হলেও সমস্ত পরীক্ষার মূল্যায়ন করে True


যদি আপনাকে প্রথম ব্যর্থ চেকের স্থানে থামার দরকার হয় তবে reduceকোন তালিকাটি একটি সাধারণ মানতে রূপান্তর করতে তৈরি তা ব্যবহার করে বিবেচনা করুন :

def check_all_conditions():
    checks = [check_size, check_color, check_tone, check_flavor]
    return reduce(lambda a, f: a or f(), checks, False)

reduce(function, iterable[, initializer]): পুনরাবৃত্তীয় আইটেমগুলিতে বাম থেকে ডানদিকে দুটি আর্গুমেন্টের ক্রিয়াকলাপ প্রয়োগ করুন, যাতে একক মানকে পুনরাবৃত্ত করতে হবে। বাম আর্গুমেন্ট, এক্স, সঞ্চিত মান এবং ডান আর্গুমেন্ট, y, হ'ল পুনরুক্তযোগ্য থেকে আপডেট মান। Alচ্ছিক প্রারম্ভক উপস্থিত থাকলে, এটি গণনার মধ্যে পুনরাবৃত্তিযোগ্য আইটেমগুলির আগে স্থাপন করা হয়

তোমার ক্ষেত্রে:

  • lambda a, f: a or f()ফাংশন চেক যে হয় সঁচায়ক যে aবা বর্তমান চেক f()হয় True। মনে রাখবেন যদি aহয় True, f()মূল্যায়ন করা হবে না।
  • checksচেক ফাংশন রয়েছে ( fল্যাম্বডা থেকে আইটেম)
  • False এটি প্রাথমিক মান, অন্যথায় কোনও চেক হয় না এবং ফলাফল সর্বদা হয় True

anyএবং reduceকার্যকরী প্রোগ্রামিংয়ের প্রাথমিক সরঞ্জাম। আমি আপনাকে দৃ train়ভাবে এগুলি প্রশিক্ষণ দিতে উত্সাহিত করি পাশাপাশি mapএটিও দুর্দান্ত!


9
anyকেবলমাত্র তখনই কাজ করে যদি চেকগুলি প্রকৃতপক্ষে আক্ষরিক Trueবা বুলিয়ান মান Falseদেয়, তবে প্রশ্নটি এটি নির্দিষ্ট করে না। reduceচেক দ্বারা প্রত্যাবর্তিত আসল মানটি ফেরত দেওয়ার জন্য আপনাকে ব্যবহার করতে হবে। এছাড়াও, anyজেনারেটর ব্যবহার করে সমস্ত চেকের মূল্যায়ন এড়ানো এড়ানো সহজ any(c() for c in (check_size, check_color, check_tone, check_flavor))লিওনহার্ডের উত্তরে
ডেভিড জেড

আমি আপনার ব্যাখ্যা এবং এর ব্যবহার পছন্দ করি reduce। @ ডেভিডজেডের মতো আমি বিশ্বাস করি যে এর সাথে আপনার সমাধানটি anyএকটি জেনারেটর ব্যবহার করা উচিত এবং এটি উল্লেখ করা দরকার যে এটি ফিরে আসা Trueবা সীমাবদ্ধ False
টিমজেব

1
@ ডেভিডজেড আসলে anyসত্যবাদী মূল্যবোধগুলির সাথে কাজ করে: any([1, "abc", False]) == Trueএবংany(["", 0]) == False
এনগাসুল

3
@ ব্লিন্ট দুঃখিত, আমি পরিষ্কার ছিলাম না। প্রশ্নের লক্ষ্য হ'ল চেকটির ফলাফল ফিরিয়ে দেওয়া (এবং চেকটি সফল হয়েছে কি ব্যর্থ হয়েছে তা কেবল নির্দেশ করে না)। আমি উল্লেখ করছিলাম যে প্রকৃত বুলিয়ান মানগুলি চেক ফাংশন থেকে ফিরিয়ে দেওয়া হলে anyকেবল সেই উদ্দেশ্যে কাজ করে works
ডেভিড জেড

19

আপনি যদি একই কোড কাঠামো চান তবে আপনি টের্নারি স্টেটমেন্ট ব্যবহার করতে পারেন!

def check_all_conditions():
    x = check_size()
    x = x if x else check_color()
    x = x if x else check_tone()
    x = x if x else check_flavor()

    return x if x else None

আমি মনে করি এটি দেখতে সুন্দর এবং স্পষ্ট দেখায়।

ডেমো:

এটির স্ক্রিনশট চলছে


7
আপনার টার্মিনালের উপরে ছোট্ট ASCII মাছের কী আছে?

36
@ লেগোস্টোরমট্রোপ্র আমি ফিশ শেলটি ব্যবহার করি, তাই আমাকে খুশি করতে আমি এএসআইআই ফিশ ট্যাঙ্ক দিয়ে সাজাই। :)
ফিনেট

3
সূক্ষ্ম মাছের জন্য ধন্যবাদ (এবং
উপায়গুলি

4
আপনি ফিশেশেল ডট কম এ মাছ পেতে পারেন , এবং এসিএসির জন্য কনফিগার ফাইলটি এখানে পেস্টবিন . com / yYVYvVeK , এছাড়াও সম্পাদকটি হ'ল পাঠ্য পাঠ্য।
ফিনেট

9
x if x else <something>শুধু কমে যাবেx or <something>

5

আমার জন্য, সেরা উত্তরটি হ'ল @ ফিল-ফ্রস্ট থেকে, তারপরে @ ওয়েইন-ওয়ার্নার্স।

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

সুতরাং আমি একক টাইপ রাখার ধারণার সাথে @ ফিলফ্রস্টের প্রতিক্রিয়াটি মিশিয়ে দেব:

def all_conditions(x):
    yield check_size(x)
    yield check_color(x)
    yield check_tone(x)
    yield check_flavor(x)

def assessed_x(x,func=all_conditions):
    for condition in func(x):
        if condition:
            return x
    return None

লক্ষ্য করুন যে xএটি একটি আর্গুমেন্ট হিসাবে পাস হয়েছে, তবে all_conditionsযাচাই করা ফাংশনগুলির একটি পাস করা জেনারেটর হিসাবে ব্যবহৃত হয় যেখানে তাদের সকলের xপরীক্ষা করা যায়, এবং ফিরে আসে Trueবা False। ব্যবহারের funcসঙ্গে all_conditionsডিফল্ট মান হিসাবে, আপনি ব্যবহার করতে পারেন assessed_x(x), অথবা আপনি মাধ্যমে আরও ব্যক্তিগতকৃত জেনারেটরের পাস করতে পারেনfunc

এইভাবে, আপনি xএকটি চেক পাস হওয়ার সাথে সাথেই পাবেন তবে এটি সর্বদা একই ধরণের হবে।


4

আদর্শভাবে, আমি পুনরায় লিখতে হবে check_ রিটার্ন ফাংশন Trueবা Falseবরং একটি মানের চেয়ে। আপনার চেকগুলি তখন হয়ে যায়

if check_size(x):
    return x
#etc

ধরে নেওয়া আপনার xঅপরিবর্তনীয় নয়, আপনার ক্রিয়াকলাপটি এখনও এটি সংশোধন করতে পারে (যদিও তারা এটি পুনরায় বরাদ্দ করতে পারে না) - তবে কোনও ক্রিয়াকলাপ checkআসলেই এটি কোনওভাবেই সংশোধন করা উচিত নয়।


3

উপরের মার্টিজেন্সের প্রথম উদাহরণে কিছুটা প্রকারের পরিবর্তন, এটি লুপের অভ্যন্তরে যদি এড়ানো যায়:

Status = None
for c in [check_size, check_color, check_tone, check_flavor]:
  Status = Status or c();
return Status

এটা কি পারে? আপনি এখনও একটি তুলনা করতে। আপনার সংস্করণে আপনি সমস্ত শর্তাদি নির্বিশেষেও পরীক্ষা করতে পারবেন এবং সত্যবাদী মানের প্রথম নজরে ফিরে আসবেন না, এই ফাংশনগুলি কত ব্যয়বহুল, তার উপর নির্ভর করুন যে এটি পছন্দসই নয়।
রিটি 43

4
@ রেটি 43: Status or c()শর্ট সার্কুই এড়াতে / শর্ট সার্কুই কলগুলিকে সত্য বলে প্রমাণিত c()হলে Statusতা মূল্যায়ন করবে, সুতরাং এই উত্তরের কোডটি ওপির কোডের চেয়ে বেশি কোনও ফাংশন কল করতে পারে না। stackoverflow.com/questions/2580136/…
নিল স্লেটার

2
পছন্দ করুন কেবলমাত্র খারাপ দিকটি আমি দেখতে পাচ্ছি যে সেরা কেসটি এখন ও (এন) এ রয়েছে কারণ তালিকার তালিকার জন্য এন বার উৎপন্ন করতে হবে, যখন ও (1) আগে প্রথম ফাংশনটি ও (1) এ সত্যবাদী কিছু ফেরত দেয় before
টিমজেব

1
হ্যাঁ ভাল পয়েন্ট। আমাকে কেবল আশা করতে হবে যে সি () প্রায়-খালি লুপটি মোছার চেয়ে মূল্যায়ন করতে কিছুটা বেশি সময় নেয়। স্বাদ চেক করতে কমপক্ষে পুরো ভাল লাগলে পুরো সন্ধ্যা লাগতে পারে।
গণিত পাঠক

3

আমি পছন্দ করি @ টাইমেজ এর এরই মধ্যে আমি যোগ করতে যে প্রকাশ চাই Noneমধ্যে returnবিবৃতি হিসাবে সংগ্রহ প্রয়োজন হয় না orপৃথক বিবৃতি মূল্যায়ন করা হয় এবং প্রথম কেউ-জিরো কেউ খালি, কেউ-কেউ ফিরিয়ে দেওয়া হয় এবং যদি কোনো ক্ষতি হয় না তারপর Noneফিরিয়ে দেওয়া হয় আছে কিনাNone না!

সুতরাং আমার check_all_conditions()ফাংশনটি এরকম দেখাচ্ছে:

def check_all_conditions():
    return check_size() or check_color() or check_tone() or check_flavor()

সাথে ব্যবহার timeitকরে number=10**7আমি বেশ কয়েকটি পরামর্শের চলমান সময়ের দিকে তাকালাম। তুলনার খাতিরে আমি কেবলমাত্র random.random()একটি স্ট্রিং ফিরে আসতে বা Noneএলোমেলো সংখ্যার ভিত্তিতে ফাংশনটি ব্যবহার করেছি । পুরো কোডটি এখানে:

import random
import timeit

def check_size():
    if random.random() < 0.25: return "BIG"

def check_color():
    if random.random() < 0.25: return "RED"

def check_tone():
    if random.random() < 0.25: return "SOFT"

def check_flavor():
    if random.random() < 0.25: return "SWEET"

def check_all_conditions_Bernard():
    x = check_size()
    if x:
        return x

    x = check_color()
    if x:
        return x

    x = check_tone()
    if x:
        return x

    x = check_flavor()
    if x:
        return x
    return None

def check_all_Martijn_Pieters():
    conditions = (check_size, check_color, check_tone, check_flavor)
    for condition in conditions:
        result = condition()
        if result:
            return result

def check_all_conditions_timgeb():
    return check_size() or check_color() or check_tone() or check_flavor() or None

def check_all_conditions_Reza():
    return check_size() or check_color() or check_tone() or check_flavor()

def check_all_conditions_Phinet():
    x = check_size()
    x = x if x else check_color()
    x = x if x else check_tone()
    x = x if x else check_flavor()

    return x if x else None

def all_conditions():
    yield check_size()
    yield check_color()
    yield check_tone()
    yield check_flavor()

def check_all_conditions_Phil_Frost():
    for condition in all_conditions():
        if condition:
            return condition

def main():
    num = 10000000
    random.seed(20)
    print("Bernard:", timeit.timeit('check_all_conditions_Bernard()', 'from __main__ import check_all_conditions_Bernard', number=num))
    random.seed(20)
    print("Martijn Pieters:", timeit.timeit('check_all_Martijn_Pieters()', 'from __main__ import check_all_Martijn_Pieters', number=num))
    random.seed(20)
    print("timgeb:", timeit.timeit('check_all_conditions_timgeb()', 'from __main__ import check_all_conditions_timgeb', number=num))
    random.seed(20)
    print("Reza:", timeit.timeit('check_all_conditions_Reza()', 'from __main__ import check_all_conditions_Reza', number=num))
    random.seed(20)
    print("Phinet:", timeit.timeit('check_all_conditions_Phinet()', 'from __main__ import check_all_conditions_Phinet', number=num))
    random.seed(20)
    print("Phil Frost:", timeit.timeit('check_all_conditions_Phil_Frost()', 'from __main__ import check_all_conditions_Phil_Frost', number=num))

if __name__ == '__main__':
    main()

এবং ফলাফল এখানে:

Bernard: 7.398444877040768
Martijn Pieters: 8.506569201346597
timgeb: 7.244275416364456
Reza: 6.982133448743038
Phinet: 7.925932800076634
Phil Frost: 11.924794811353031

2

এই উপায়টি বাক্সের বাইরে কিছুটা হলেও, আমি মনে করি শেষ ফলাফলটি সহজ, পঠনযোগ্য এবং সুন্দর দেখাচ্ছে looks

মৌলিক ধারণাটি raiseব্যতিক্রম হয় যখন কার্যগুলির মধ্যে একটি সত্যবাদী হিসাবে মূল্যায়ন করে এবং ফলাফলটি ফেরত দেয়। এটি দেখতে কেমন হতে পারে তা এখানে:

def check_conditions():
    try:
        assertFalsey(
            check_size,
            check_color,
            check_tone,
            check_flavor)
    except TruthyException as e:
        return e.trigger
    else:
        return None

assertFalseyযখন আপনাকে ডাকা ফাংশন আর্গুমেন্টগুলির মধ্যে একটি সত্যবাদী হিসাবে মূল্যায়ন করে তখন আপনাকে একটি ফাংশন প্রয়োজন যা একটি ব্যতিক্রম উত্থাপন করে:

def assertFalsey(*funcs):
    for f in funcs:
        o = f()
        if o:
            raise TruthyException(o)

উপরেরগুলি সংশোধন করা যেতে পারে যাতে কার্যকারিতা মূল্যায়নের জন্য যুক্তিও সরবরাহ করতে পারে।

এবং অবশ্যই আপনার TruthyExceptionনিজের প্রয়োজন হবে । এই ব্যতিক্রমটি objectব্যতিক্রমটিকে ট্রিগার করিয়ে দেয়:

class TruthyException(Exception):
    def __init__(self, obj, *args):
        super().__init__(*args)
        self.trigger = obj

আপনি অবশ্যই মূল ফাংশনটিকে আরও সাধারণ কিছুতে পরিণত করতে পারেন, অবশ্যই:

def get_truthy_condition(*conditions):
    try:
        assertFalsey(*conditions)
    except TruthyException as e:
        return e.trigger
    else:
        return None

result = get_truthy_condition(check_size, check_color, check_tone, check_flavor)

এটি কিছুটা ধীর হতে পারে কারণ আপনি দুটিই ব্যবহার করছেন if বিবৃতি এবং একটি ব্যতিক্রম পরিচালনা করছেন। তবে ব্যতিক্রমটি কেবলমাত্র সর্বোচ্চ এক বার পরিচালিত হয়, সুতরাং আপনি চেকটি চালানোর এবং Trueহাজার হাজার বার কোনও মূল্য না পাওয়ার প্রত্যাশা না করলে পারফরম্যান্সের হিট সামান্য হওয়া উচিত ।


//, কিউট! এই ধরণের জিনিসটির জন্য ব্যতিক্রম হ্যান্ডলিং ব্যবহার করা কি "পাইথোনিক" হিসাবে বিবেচিত হয়?
নাথান বাসানিজ

@ নাথানবাসানিজ শিওর- ব্যতিক্রমগুলি সর্বদা নিয়ন্ত্রণ প্রবাহের জন্য ব্যবহৃত হয়। StopIterationএটি একটি দুর্দান্ত উদাহরণ: আপনি একবারে পুনরাবৃত্তিযোগ্য প্রস্থান করার সময় প্রতি ব্যতিক্রম উত্থাপিত হয়। আপনি যে জিনিসটি এড়াতে চান তা হ'ল ক্রমাগতভাবে ব্যতিক্রম বারবার উত্থাপন করা, যা ব্যয়বহুল হবে। তবে এটি এক সময় করা হয় না।
রিক

//, আহ, আমি তা গ্রহণ তোমার মত কিছু উল্লেখ করছি programmers.stackexchange.com/questions/112463/... । আমি এই প্রশ্নের পক্ষে এবং এই উত্তরের জন্য ভোট দিয়েছি। পাইথন 3 এর জন্য 3 ডক্স এখানে রয়েছে: ডকস.পিথন.আর. / 3 / লাইবারি / স্টাডটাইপস html # iterator- প্রকার , আমার মনে হয়।
নাথান বাসানিজ

1
আপনি একটি সাধারণ-উদ্দেশ্যমূলক ক্রিয়াকলাপ এবং একটি ব্যতিক্রম সংজ্ঞায়িত করতে চান, কোথাও অন্য কোনও ক্রিয়ায় কয়েকটি চেক করতে চান? আমি মনে করি এটি কিছুটা বেশি।
ব্ল্যাকলাইট শাইনিং

নিবন্ধন করুন আমি আসলে এটি নিজেই কখনই করতাম না। ওপি পুনরাবৃত্তি কোড এড়ানোর উপায় চেয়েছিল, তবে আমি মনে করি তিনি যা শুরু করেছিলেন তা পুরোপুরি ঠিক আছে perfectly
রিক

2

পাইথোনিক উপায় হ'ল হ্রাস (যেমন ইতিমধ্যে উল্লিখিত কেউ) বা ইটারটোলগুলি (নীচে দেখানো হয়েছে) ব্যবহার করছে তবে এটি আমার কাছে মনে হয় কেবল orঅপারেটরের সংক্ষিপ্ত সার্কিট ব্যবহার করে পরিষ্কার কোড তৈরি করে

from itertools import imap, dropwhile

def check_all_conditions():
    conditions = (check_size,\
        check_color,\
        check_tone,\
        check_flavor)
    results_gen = dropwhile(lambda x:not x, imap(lambda check:check(), conditions))
    try:
        return results_gen.next()
    except StopIteration:
        return None

0

আমি এখানে লাফিয়ে যাচ্ছি এবং পাইথনের একটি লাইন কখনও লিখিনি, তবে আমি ধরে নিই if x = check_something(): return x ?

যদি তাই:

def check_all_conditions():

    if (x := check_size()): return x
    if (x := check_color()): return x
    if (x := check_tone()): return x
    if (x := check_flavor()): return x

    return None

1
এটি বৈধ পাইথন নয়, না। পাইথন আপনাকে অ্যাসাইনমেন্ট অপারেটরটি এর মতো ব্যবহার করতে দেয় না। তবে খুব সম্প্রতি একটি নতুন বিশেষ অ্যাসাইনমেন্ট এক্সপ্রেশন যুক্ত হয়েছিল, সুতরাং আপনি এখন if ( x := check_size() ) :একই প্রভাবের জন্য লিখতে পারেন ।
জ্যাক এইডলি

0

বা ব্যবহার করুন max:

def check_all_conditions():
    return max(check_size(), check_color(), check_tone(), check_flavor()) or None

-2

অতীতে আমি dicts এর সাথে স্যুইচ / কেস স্টেটমেন্টের কিছু আকর্ষণীয় বাস্তবায়ন দেখেছি যা আমাকে এই উত্তরের দিকে নিয়ে গেছে। আপনি যে উদাহরণ সরবরাহ করেছেন তা ব্যবহার করে আপনি নিম্নলিখিত পাবেন। (এটি উন্মাদনা using_complete_sentences_for_function_names, তাই নতুন check_all_conditionsনামকরণ করা হয়েছে statusSee দেখুন (1))

def status(k = 'a', s = {'a':'b','b':'c','c':'d','d':None}) :
  select = lambda next, test : test if test else next
  d = {'a': lambda : select(s['a'], check_size()  ),
       'b': lambda : select(s['b'], check_color() ),
       'c': lambda : select(s['c'], check_tone()  ),
       'd': lambda : select(s['d'], check_flavor())}
  while k in d : k = d[k]()
  return k

নির্বাচিত ফাংশন প্রতিটি check_FUNCTIONবার দুটি কল করার প্রয়োজনকে বাদ দেয় অর্থাৎ আপনি এড়াতে পারেনcheck_FUNCTION() if check_FUNCTION() else next অন্য ফাংশন স্তর যুক্ত করে । এটি দীর্ঘ চলমান ফাংশনগুলির জন্য দরকারী। ডিকের ল্যাম্বডাস এর মানগুলি কার্যকর করতে বিলম্ব না করা পর্যন্ত বিলম্ব করে।

বোনাস হিসাবে আপনি এক্সিকিউশন অর্ডারটি পরিবর্তন করতে পারেন এবং কিছু পরিবর্তন kএবং sউদাহরণস্বরূপ এড়িয়ে যেতে পারেন egk='c',s={'c':'b','b':None} পরীক্ষার সংখ্যা হ্রাস করে এবং মূল প্রক্রিয়াকরণ আদেশটিকে বিপরীত করে।

দ্য timeitফেলোগণ খোঁজা কিন্তু আপনি আরো কোডের সৌন্দর্য্য সঙ্গে সংশ্লিষ্ট বলে মনে হচ্ছে একটি অতিরিক্ত স্তর বা স্ট্যাক দুটি এবং অভি জন্য খরচ যোগ করার খরচ বেশি দর কষাকষি হতে পারে।

বিকল্পভাবে একটি সহজ বাস্তবায়ন নিম্নলিখিত হতে পারে:

def status(k=check_size) :
  select = lambda next, test : test if test else next
  d = {check_size  : lambda : select(check_color,  check_size()  ),
       check_color : lambda : select(check_tone,   check_color() ),
       check_tone  : lambda : select(check_flavor, check_tone()  ),
       check_flavor: lambda : select(None,         check_flavor())}
  while k in d : k = d[k]()
  return k
  1. আমি এর অর্থ পিপ 8 এর শর্ত নয়, একটি বাক্যের পরিবর্তে একটি সংক্ষিপ্ত বর্ণনামূলক শব্দ ব্যবহারের শর্তে। মঞ্জুর করা হয়েছে যে ওপি কিছু কোডিং কনভেনশন অনুসরণ করছে, একটি বিদ্যমান কোড বেস ব্যবহার করছে বা তাদের কোডবেসে সংক্ষিপ্ত শর্তাদি যত্ন করছে না।

1
কখনও কখনও লোকেরা তাদের নামকরণের সাথে সত্যই ক্রেজি হয়ে যায় যখন একটি শব্দ করবে। ওপির কোডটিকে উদাহরণ হিসাবে ব্যবহার করা অসম্ভাব্য যে তার কল করা ফাংশন হবে check_no/some/even/prime/every_third/fancy_conditionsতবে কেবল এই একটি ফাংশন তাই কেন এটি কল করবেন না statusবা যদি কেউ জোর দেয় তবে check_status। ব্যবহার _all_অতিমাত্রায় ব্যবহৃত, তিনি মহাবিশ্বের অখণ্ডতা নিশ্চিত করছেন না। নামকরণ অবশ্যই যখনই সম্ভব সম্ভাব্য কিওয়ার্ডের লিভারেজ ব্যবস্থার জন্য একটি সামঞ্জস্যপূর্ণ সেট ব্যবহার করা উচিত। দীর্ঘতম বাক্যগুলি ডকাস্ট্রিং হিসাবে সেরা পরিবেশন করে। একটি সংক্ষেপে কিছু বর্ণনা করার জন্য খুব কমই 8-10 অক্ষরের বেশি প্রয়োজন।
ক্যারেল

1
আমি দীর্ঘ ফাংশন নামের ভক্ত, কারণ আমি উচ্চ-স্তরের ফাংশনগুলি স্ব-ডকুমেন্টিং করতে চাই। তবে check_all_conditionsএটি একটি খারাপ নাম, কারণ এটি সত্য হলে এটি সমস্ত শর্ত পরীক্ষা করে না । আমি এরকম কিছু ব্যবহার করব matches_any_condition
জন হাজেন

এটি গ্রহণ করা একটি আকর্ষণীয় কৌশল। আমি পরে টাইপগুলি তৈরি করব এমন চিঠিগুলির সংখ্যা হ্রাস করার চেষ্টা করব :) মনে হচ্ছে আমি আমার সমাধানটিতে মতামতের একটি স্তূপ বজায় রেখেছি, যখন আমি সত্যিই একটি সহায়ক ইঙ্গিত দেওয়ার চেষ্টা করছিলাম। এটি কি সম্পাদনা করা উচিত?
ক্যারেল

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

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