العودة تأكل الاستثناء
سؤال
لقد وجدت السلوك التالي على الأقل غريب:
def errors():
try:
ErrorErrorError
finally:
return 10
print errors()
# prints: 10
# It should raise: NameError: name 'ErrorErrorError' is not defined
يختفي الاستثناء عند الاستخدام return
داخل finally
بند.هل هذا خطأ؟هل تم توثيق ذلك في أي مكان؟
لكن السؤال الحقيقي (والإجابة التي سأضع علامة على أنها صحيحة) هو:
ما هو سبب مطوري بايثون للسماح بهذا السلوك الغريب؟
المحلول
وسألت عن المنطق المطورين بيثون. لا أستطيع أن أتكلم بالنسبة لهم، ولكن لا تقدم أي سلوك آخر معانيها. ويمكن للوظيفة إما بإرجاع قيمة، أو أنه يمكن رفع استثناء. فإنه لا يمكن القيام بالأمرين معا. الغرض من عبارة "أخيرا" هو توفير رمز تنظيف هذا هو "مضمونة" ليتم تشغيلها، بغض النظر عن الاستثناءات. عن طريق وضع عبارة إرجاع في بند أخيرا، كنت قد أعلنت الذي تريد إرجاع قيمة، مهما كانت، بغض النظر عن الاستثناءات. إذا تصرف بيثون كما كنت طالبا ورفعت استثناء، سيكون من كسر العقد شرط "أخيرا" (لأنه سيفشل لإرجاع القيمة قلت لها بالعودة).
نصائح أخرى
يختفي الاستثناء عند الاستخدام
return
داخلfinally
بند...هل تم توثيق ذلك في أي مكان؟
إذا كان موجودًا أخيرًا، فإنه يحدد معالج "التنظيف".يتم تنفيذ جملة المحاولة، بما في ذلك أي عبارات باستثناء و else.إذا حدث استثناء في أي من البنود ولم تتم معالجته، فسيتم حفظ الاستثناء مؤقتًا.يتم تنفيذ الجملة النهائية.إذا كان هناك استثناء محفوظ، فسيتم إعادة طرحه في نهاية الجملة الأخيرة. إذا أثارت الجملة النهائية استثناءً آخر أو نفذت عبارة إرجاع أو فاصل، فسيتم فقدان الاستثناء المحفوظ.
وهنا هو مقارنة مثيرة للاهتمام للعودة في منع أخيرا، بين - جاوة / C # / بيثون / جافا سكريبت: (<لأ href = "https://web.archive.org/web/20120426091446/http://www. gettingclever.com/2008/07/return-from-finally.html "يختلط =" نوفولو noreferrer "> أرشيف صلة )
<اقتباس فقرة>عودة من وأخيرا
واليوم فقط كنت أساعد مع بعض الأخطاء في جاوة وجاء عبر مشكلة مثيرة للاهتمام - ماذا يحدث إذا كنت تستخدم العودة في غضون حاول / catch بيان؟ يجب إطلاق القسم في النهاية أم لا؟ I تبسيط المشكلة التالية مقتطف الشفرة:
وماذا الطباعة البرمجية التالية من؟
class ReturnFromFinally {
public static int a() {
try {
return 1;
}
catch (Exception e) {}
finally{
return 2;
}
}
public static void main(String[] args) {
System.out.println(a());
}
}
وتخميني الأولي سيكون، وأنه يجب طباعة 1
، ادعو
return
، لذلك أفترض، سيتم إرجاع واحد. ومع ذلك، فإنه ليس من
الحالة:
وأنا أفهم منطق، وأخيرا لابد من تنفيذ القسم، ولكن بطريقة ما أشعر بعدم الارتياح حول هذا الموضوع. دعونا نرى ما # C يفعل في هذه الحالة:
class ReturnFromFinally
{
public static int a()
{
try {
return 1;
}
catch (System.Exception e) {}
finally
{
return 2;
}
}
public static void Main(string[] args)
{
System.Console.WriteLine(a());
}
}
وأنا أفضل بكثير بل هذا السلوك، التحكم في التدفق لا يمكن عبثوا في البند أخيرا، لذلك يمنعنا من اطلاق النار بنفسي في القدم. فقط من أجل اكتمالها، دعونا تحقق ما غيرها اللغات القيام به.
وبيثون:
def a():
try:
return 1
finally:
return 2
print a()
وجافا سكريبت:
<script>
function ReturnFromFinally()
{
try
{
return 1;
}
catch (e)
{
}
finally
{
return 2;
}
}
</script>
<a onclick="alert(ReturnFromFinally());">Click here</a>
وليس هناك بند في النهاية في C ++ و PHP، لذلك لا أستطيع أن محاولة الخروج من الماضي لغتين لدي مترجم / مترجم لل.
أظهروتجربتنا قليلا لطيف، أن C # لديه اجمل نهج لهذه المشكلة، ولكن فوجئت جدا للتعلم، أن جميع لغات أخرى التعامل مع المشكلة بنفس الطريقة.
اقتباس فقرة>العودة من النهاية هي لا فكرة جيدة.أعلم أن C# يمنع على وجه التحديد القيام بذلك.