অজগর যদি চেষ্টা বনাম ব্যবহার করে


145

ভেরিয়েবলের মান রাখার জন্য পরীক্ষা করার সময় কোনটি ব্যবহার tryবা ifনির্মাণের সিদ্ধান্ত নেওয়ার যৌক্তিকতা আছে?

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

result = function();
if (result):
    for r in result:
        #process items

অথবা

result = function();
try:
    for r in result:
        #process items
except TypeError:
    pass;

সম্পর্কিত আলোচনা:

পাইথনে সদস্য অস্তিত্বের জন্য অনুসন্ধান করা হচ্ছে


মনে রাখবেন যে যদি আপনার # প্রসেসের আইটেমের স্তরের কোনও প্রকারেরর ফেলে দেওয়ার জন্য দায়বদ্ধ থাকে তবে আপনাকে আর একটি চেষ্টাতে মোড়তে হবে: বাদে: ব্লক করুন। এই সুনির্দিষ্ট উদাহরণের জন্য আমি কেবলমাত্র যদি একটি ব্যবহার করে থাকি তবে:
richo

উত্তর:


237

আপনি প্রায়শই শুনেন যে পাইথন ইএএফপি শৈলীতে উত্সাহ দেয় ("অনুমতি চেয়ে ক্ষমা চাওয়া সহজ") ("আপনি লাফানোর আগে দেখুন")। আমার কাছে এটি দক্ষতা এবং পঠনযোগ্যতার বিষয়।

আপনার উদাহরণে (বলুন যে কোনও তালিকা বা খালি স্ট্রিংয়ের পরিবর্তে ফাংশনটি একটি তালিকা ফেরত দেবে বা None), যদি আপনি আশা করেন যে 99% সময়ের মধ্যে resultআসলে পুনরাবৃত্তিযোগ্য কিছু থাকবে তবে আমি এই try/exceptপদ্ধতির ব্যবহার করব । ব্যতিক্রমগুলি সত্যই ব্যতিক্রমী হলে এটি আরও দ্রুত হবে। যদি resultহয় None, সময় চেয়ে বেশি 50% তারপর ব্যবহার ifসম্ভবত উত্তম।

কয়েকটি পরিমাপ সহ এটি সমর্থন করতে:

>>> import timeit
>>> timeit.timeit(setup="a=1;b=1", stmt="a/b") # no error checking
0.06379691968322732
>>> timeit.timeit(setup="a=1;b=1", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.0829463709378615
>>> timeit.timeit(setup="a=1;b=0", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.5070195056614466
>>> timeit.timeit(setup="a=1;b=1", stmt="if b!=0:\n a/b")
0.11940114974277094
>>> timeit.timeit(setup="a=1;b=0", stmt="if b!=0:\n a/b")
0.051202772912802175

সুতরাং, যেখানে কোনও ifবিবৃতি সর্বদা আপনার জন্য ব্যয় করে সেখানে একটি try/exceptব্লক সেটআপ করা প্রায় বিনামূল্যে । কিন্তু Exceptionআসলে যখন ঘটে তখন ব্যয় অনেক বেশি হয়।

নৈতিক:

  • try/exceptপ্রবাহ নিয়ন্ত্রণের জন্য এটি পুরোপুরি ঠিক আছে (এবং "পাইথোনিক") ,
  • এসগুলি Exceptionআসলে ব্যতিক্রমী হয় তবে এটি সার্থক হয়।

পাইথন ডক্স থেকে:

EAFP

অনুমতি চেয়ে ক্ষমা চাইতে সহজ। এই সাধারণ পাইথন কোডিং শৈলীটি বৈধ কী বা বৈশিষ্ট্যগুলির অস্তিত্ব ধরে নিয়েছে এবং যদি অনুমানটি মিথ্যা প্রমাণিত হয় তবে ব্যতিক্রমগুলি ধরবে। এই পরিষ্কার এবং দ্রুত শৈলীটি অনেকের উপস্থিতি tryএবং exceptবিবৃতি দ্বারা চিহ্নিত করা হয় । কৌশলটি সি অন্যান্য হিসাবে অনেক অন্যান্য ভাষায় সাধারণ LBYL শৈলীর সাথে বিপরীতে রয়েছে ts


1
ধন্যবাদ. আমি দেখি যে এক্ষেত্রে যুক্তিই ফলাফলের প্রত্যাশা হতে পারে।
আর্টডানিল 21

6
.... এবং এটি পাইথনের পক্ষে সত্যিকারের অনুকূল জেআইটি করা এত কঠিন কারণ ( হিসাবে বিটা সম্প্রতি LuaJIT 2 প্রমাণ করে, ডায়নামিক ভাষায় পারেন সত্যিই সত্যিই দ্রুত; তবে এটি প্রাথমিকভাবে ভাষা নকশা এবং এটি উত্সাহিত করে এমন স্টাইলের উপর খুব বেশি নির্ভর করে। (সম্পর্কিত নোটে, ভাষা নকশা কেন এমনকি খুব ভাল জাভাস্ক্রিপ্ট জেআইটিও লুয়াজিট ১ এর সাথে তুলনা করতে পারে না, খুব কম 2)
জাভিয়ের

1
@ 2rs2ts: আমি ঠিক একই সময় নিজেই করেছি। পাইথন 3-এ, অভিধানে কী ছিল এমন ক্ষেত্রেগুলির try/exceptতুলনায় 25% দ্রুত if key in d:ছিল। প্রত্যাশার মতো কীটি অভিধানে না থাকলে এটি অনেক ধীর ছিল এবং এই উত্তরটির সাথে সামঞ্জস্য ছিল।
টিম পিটজ্যাকার

5
আমি জানি এটি একটি পুরানো উত্তর, তবে: 1/1টাইমিটের মতো বিবৃতি ব্যবহার করা দুর্দান্ত পছন্দ নয়, কারণ সেগুলি অপ্টিমাইজ হবে (দেখুন dis.dis('1/1')এবং দেখুন যে কোনও বিভাজন ঘটে না)।
Andrea Corbellini

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

14

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

for r in function():
    # process items

2
আমি সেই বিষয়ে আপনার সাথে পুরোপুরি একমত; তবে, ফাংশনটি আমার নয়, এবং আমি এটি ব্যবহার করছি।
আর্টডানিল 21

2
@ আর্টডানিল: সুতরাং আপনি সেই ফাংশনটি এমন একটিতে মুড়ে ফেলতে পারেন যা আপনি লিখেছেন যা ব্র্যান্ডন করফম্যান যে ভাবনাটির মতো কাজ করে।
কুমারানা

24
যা প্রশ্নটি উত্থাপন করে: মোড়কটি যদি না-পুনরাবৃত্তিযোগ্য কেসগুলি হ্যান্ডেল করার চেষ্টা করে তবে একটি ব্যবহার করা উচিত?
jcdyer

@ কুমরানা যা আমি ঠিক তাই করার চেষ্টা করছি। @ জিসিডি যেমন উল্লেখ করেছে, প্রশ্নটি আমার মোড়কের কার্যের পরিস্থিতিটি কীভাবে পরিচালনা করা উচিত সে সম্পর্কে is
আর্টদানিল

12

আমি প্রদত্ত কোডটি যদি প্রথম নজরে সুস্পষ্ট না হয় এবং কোড নমুনার পরে আপনাকে ব্যাখ্যাটি পড়তে হবে তবে দয়া করে আমার সমাধানটিকে উপেক্ষা করুন।

আমি কি ধরে নিতে পারি যে "কোনও মূল্য ফেরত দেওয়া হয়নি" তার অর্থ ফেরতের মান কোনওটি নয়? যদি হ্যাঁ, বা "কোন মান" মিথ্যা বুলিয়ান-ভিত্তিক হয় তবে আপনি নিম্নলিখিতটি করতে পারেন, যেহেতু আপনার কোডটি মূলত "কোনও মানকে" "পুনরাবৃত্তি না করে" হিসাবে বিবেচনা করে:

for r in function() or ():
    # process items

যদি function()সত্য কিছু নয় এমন কিছু প্রদান করে, আপনি খালি টিপলটি দিয়ে পুনরাবৃত্তি করেন, অর্থাৎ আপনি কোনও পুনরাবৃত্তি চালান না। এটি মূলত এলবিওয়াইএল।


4

আপনার দ্বিতীয় উদাহরণটি ভাঙা হয়েছে - কোডটি কোনও টাইপরর ব্যতিক্রম কখনই ফেলবে না কারণ আপনি উভয় স্ট্রিং এবং তালিকার মাধ্যমে পুনরাবৃত্তি করতে পারেন rate একটি খালি স্ট্রিং বা তালিকার মাধ্যমে আইট্রেট করাও বৈধ - এটি লুপের শূন্য বারের দেহকে কার্যকর করবে।


4

নিম্নলিখিতগুলির মধ্যে কোনটি বেশি পছন্দনীয় হবে এবং কেন?

আপনি লাফ দেওয়ার আগে দেখুন এই ক্ষেত্রে ভাল। ব্যতিক্রম পদ্ধতির সাহায্যে আপনার টাইপ এরর আপনার লুপের শরীরে যে কোনও জায়গায় ঘটতে পারে এবং এটি ধরা পড়ে ফেলে দেওয়া হবে যা আপনি চান না এবং এটি ডিবাগিংয়ের কৌশলটিকে জটিল করে তুলবে।

(যদিও আমি ব্র্যান্ডন কর্ফম্যানের সাথে একমত: খালি তালিকার পরিবর্তে 'আইটেম' দেওয়ার জন্য কোনওটিই ফিরিয়ে দেওয়া নয় is এটি জাভা কোডারগুলির একটি অপ্রীতিকর অভ্যাস যা পাইথনে দেখা উচিত নয় Or বা জাভা))


4

সাধারণত, আমি যে ধারণা অর্জন করেছি তা ব্যতিক্রমী পরিস্থিতিতে ব্যতিক্রমগুলি সংরক্ষণ করা উচিত for যদি resultপ্রত্যাশিত হয় যে কখনই শূন্য না হয় (তবে এটি হতে পারে, উদাহরণস্বরূপ, কোনও ডিস্ক ক্র্যাশ হয়ে গেছে ইত্যাদি), দ্বিতীয় পদ্ধতির অর্থ হয়। অন্যদিকে, resultযদি খালিটি সাধারণ অবস্থার অধীনে পুরোপুরি যুক্তিসঙ্গত হয় তবে ifবিবৃতি দিয়ে এর জন্য পরীক্ষা করা আরও অর্থবোধ করে।

আমি (আরও সাধারণ) দৃশ্যের কথা মনে রেখেছিলাম:

# keep access counts for different files
file_counts={}
...
# got a filename somehow
if filename not in file_counts:
    file_counts[filename]=0
file_counts[filename]+=1

সমমানের পরিবর্তে:

...
try:
    file_counts[filename]+=1
except KeyError:
    file_counts[filename]=1

টিম পিটজেকারের উল্লেখযোগ্য পদ্ধতির মধ্যে পার্থক্যের এটি একটি উদাহরণ: প্রথমটি এলবিওয়াইএল, দ্বিতীয়টি
ইএএফপি

++অজগরের কাজ করে না এমন একটি দ্রুত নোট , += 1পরিবর্তে ব্যবহার করুন।
tgray

3

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

result = function();
try:
    it = iter(result)
except TypeError:
    pass
else:
    for r in it:
        #process items

আপনি দেখতে পাচ্ছেন, এটি বরং কুরুচিপূর্ণ। আমি এটি প্রস্তাব করি না, তবে এটি সম্পূর্ণতার জন্য উল্লেখ করা উচিত।


আমার দৃষ্টিতে, ত্রুটিযুক্ত ত্রুটিগুলি ইচ্ছাকৃতভাবে চালানো সবসময় খারাপ কোডিং স্টাইল। কোনও বিকাশকারীকে কী আশা করতে হবে তা জানতে হবে এবং ব্যতিক্রম ছাড়াই সেই মানগুলি পরিচালনা করতে প্রস্তুত থাকতে হবে। যখনই কোনও অপারেশন যা করার কথা ছিল তা করেছিল (প্রোগ্রামারের দৃষ্টিকোণ থেকে) এবং প্রত্যাশিত ফলাফলগুলি একটি তালিকা বা None, সর্বদা is Noneবা এর সাথে ফলাফলটি পরীক্ষা করে is not None। অন্যদিকে বৈধ ফলাফলের জন্য ব্যতিক্রমগুলি উত্থাপন করা খারাপ স্টাইলও। ব্যতিক্রমগুলি অপ্রত্যাশিত জিনিসগুলির জন্য। উদাহরণ: str.find()কিছুই না পাওয়া গেলে -1 প্রদান করে কারণ অনুসন্ধানটি ত্রুটি ছাড়াই শেষ হয়েছে completed
বাচসৌ

1

যতক্ষণ পারফরম্যান্সের সাথে সম্পর্কিত হয়, কোডের জন্য সাধারণত চেষ্টা করুন ব্লকটি ব্যবহার করুন যা সাধারণত ব্যতিক্রমগুলি উত্থাপন করে না যদি প্রতিবার স্টেটমেন্ট ব্যবহার করা হয় তার চেয়ে দ্রুত। সুতরাং, সিদ্ধান্ত বহিরাগত ক্ষেত্রে সম্ভাব্যতার উপর নির্ভর করে।


-5

থাম্বের একটি সাধারণ নিয়ম হিসাবে, আপনার প্রবাহ নিয়ন্ত্রণ করতে কখনও চেষ্টা / ধরা বা কোনও ব্যতিক্রম হ্যান্ডলিং স্টাফ ব্যবহার করা উচিত নয় । যদিও পর্দার পিছনে পুনরাবৃত্তি StopIterationব্যতিক্রম উত্থাপনের মাধ্যমে নিয়ন্ত্রণ করা হয় , তবুও আপনার দ্বিতীয় কোড স্নিপেটকে দ্বিতীয়টির চেয়ে পছন্দ করা উচিত।


7
জাভাতে এটি সত্য। পাইথন ইএএফপিকে বেশ ভারী করে।
ফেংবি

3
এটি এখনও একটি বিজোড় অনুশীলন বেশিরভাগ প্রোগ্রামারদের ব্রেইনগুলি আমার অভিজ্ঞতায় ইএএফপি ছাড়ার জন্য তারযুক্ত। কেন তারা নির্দিষ্ট পথ বেছে নেওয়া হয়েছিল তা নিয়ে তারা অবাক হয়ে যায়। এটি বলা হচ্ছে, প্রতিটি নিয়ম ভাঙার একটি সময় এবং জায়গা রয়েছে।
ilowe
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.