أفضل الممارسات في بيثون عن قيمة المقابل على خطأ مقابلالنجاح

StackOverflow https://stackoverflow.com/questions/1630706

  •  06-07-2019
  •  | 
  •  

سؤال

في العامة, دعونا نقول لديك طريقة مثل أدناه.

def intersect_two_lists(self, list1, list2):
    if not list1:
        self.trap_error("union_two_lists: list1 must not be empty.")
        return False
    if not list2:
        self.trap_error("union_two_lists: list2 must not be empty.")
        return False
    #http://bytes.com/topic/python/answers/19083-standard
    return filter(lambda x:x in list1,list2)

في هذا الأسلوب خاصة عندما تم العثور على أخطاء, لا أريد أن إرجاع قائمة فارغة في هذه الحالة لأن ذلك يمكن أن يكون الجواب الحقيقي لهذا محددة استدعاء الأسلوب ، أريد أن أعود شيء للإشارة إلى معلمات غير صحيحة.لذا عدت كاذبة على خطأ في هذه الحالة ، قائمة على خلاف ذلك (فارغة أو لا).

سؤالي هو ما هي أفضل الممارسات في مجالات مثل هذا ، ليس فقط في القوائم ؟ عودة أيما أريد التأكد من أنني الوثيقة للمستخدم القراءة ؟ :-) ماذا تفعل معظم الناس القيام به:

  1. إذا على النجاح الذي كان من المفترض أن يعود صحيحة أو خاطئة و قبض خطأ ؟
  2. إذا على النجاح الذي كان من المفترض أن يعود القائمة على الصيد خطأ ؟
  3. إذا على النجاح الذي كان من المفترض أن يعود مقبض الملف و يمكنك التقاط خطأ ؟
  4. الخ
هل كانت مفيدة؟

المحلول

أولا مهما فعلت لا إرجاع نتيجة و رسالة خطأ.هذه طريقة سيئة حقا لمعالجة الأخطاء وسوف يسبب لك الصداع لا نهاية لها. إذا كنت بحاجة إلى بيان خطأ دائما رفع استثناء.

وعادة ما تميل إلى تجنب إثارة الأخطاء إلا إذا كان ذلك ضروريا.في المثال الخاص بك رمي خطأ ليست هناك حاجة حقا.المتقاطعة قائمة فارغة مع غير واحد فارغ ليس خطأ.والنتيجة هي مجرد قائمة فارغة و هذا هو الصحيح.ولكن دعونا نقول كنت ترغب في التعامل مع حالات أخرى.على سبيل المثال إذا كان الأسلوب حصلت غير قائمة النوع.في هذه الحالة فمن الأفضل أن رفع استثناء.استثناء شيء لكنهم يخشون من.

نصيحتي لك هو أن ننظر إلى بيثون مكتبة وظائف مماثلة وانظر كيف بيثون يتعامل مع تلك الحالات الخاصة.على سبيل المثال إلقاء نظرة على طريقة التقاطع في المجموعة ، فإنه يميل إلى أن يكون متسامحا.هنا أنا أحاول أن تتقاطع مجموعة فارغة مع قائمة فارغة:

>>> b = []
>>> a = set()
>>> a.intersection(b)
set([])

>>> b = [1, 2]
>>> a = set([1, 3])
>>> a.intersection(b)
set([1])

أخطاء فقط القيت عند الحاجة:

>>> b = 1
>>> a.intersection(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

بالتأكيد هناك حالات حيث تعود صحيحة أو خاطئة على النجاح أو الفشل يمكن أن تكون جيدة.ولكن من المهم جدا أن تكون متسقة.وظيفة يجب العودة دائما نفس النوع أو هيكل.هو مربكة جدا أن يكون وظيفة التي يمكن أن عودة قائمة أو منطقية.أو العودة نفس النوع ولكن معنى هذه القيمة يمكن أن تكون مختلفة في حالة وجود خطأ.

تحرير:

OP يقول:

أريد أن أعود شيء للإشارة إلى معلمات غير صحيحة.

لا شيء يقول هناك خطأ أفضل من استثناء.إذا كنت تريد أن تشير إلى معلمات غير صحيحة ثم استخدام الاستثناءات ووضع مفيدة رسالة الخطأ.يعود نتيجة لذلك في هذه الحالة هو فقط مربكة.ربما هناك حالات أخرى حيث كنت تريد أن تشير إلى أن لا شيء قد حدث ولكن ليس خطأ.على سبيل المثال إذا كان لديك طريقة حذف إدخالات من الجدول دخول طلب الحذف غير موجود.في هذه الحالة قد يكون على ما يرام فقط عودة صحيحة أو خاطئة على النجاح أو الفشل.ذلك يعتمد على التطبيق و المقصود السلوك

نصائح أخرى

سيكون من الأفضل أن رفع استثناء من بإرجاع قيمة خاصة.هذا هو بالضبط ما الاستثناءات صممت لتحل محل رموز الخطأ مع أكثر قوة وتنظيما معالجة الأخطاء الآلية.

class IntersectException(Exception):
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return self.msg

def intersect_two_lists(self, list1, list2):
    if not list1: raise IntersectException("list1 must not be empty.")
    if not list2: raise IntersectException("list2 must not be empty.")

    #http://bytes.com/topic/python/answers/19083-standard
    return filter(lambda x:x in list1,list2)

في هذه الحالة المحددة على الرغم ربما كنت مجرد قطرة الاختبارات.لا يوجد شيء خاطئ مع تقاطع فارغة قوائم حقا.أيضا lambda هو نوع من الإحباط في هذه الأيام في الأفضلية قائمة comprehensions.انظر تجد تقاطع اثنين من القوائم ؟ عن عدة طرق لكتابة هذا دون استخدام lambda.

أود أن عودة tuple:

(صحيح some_result)

(كاذبة ، some_useful_response)

على some_useful_response الكائن يمكن أن تستخدم في التعامل مع عودة حالة أو يمكن أن تؤدي إلى عرض معلومات التصحيح.

ملاحظة:هذا الأسلوب ينطبق على عودة القيم من أي نوع.وينبغي أن لا يكون مخطئا مع باستثناء الحالات.

على المتلقي ، عليك فقط فك:

رمز الاستجابة = some_function(...)

هذا الأسلوب ينطبق على "طبيعية" التحكم في التدفق:يجب على المرء أن استخدام الاستثناء الوظيفة عند بعض غير متوقع المدخلات / تجهيز تحدث.

الجدير بالذكر أيضا: هذا الأسلوب يساعد على تطبيع وظيفة العوائد.كل مبرمج المستخدم من الوظائف أعرف ما يمكن توقعه.

تنويه:لقد جئت من إرلانج الخلفية :-)

الاستثناءات هي بالتأكيد أفضل (وأكثر Pythonic) من حالة العودة.للحصول على أكثر من ذلك بكثير على هذا: الاستثناءات مقابلحالة العودة

الحالة العامة هو رمي استثناءات في ظروف استثنائية.أتمنى أن تذكر اقتباس (أو من قال ذلك), ولكن يجب أن نسعى جاهدين للحصول على الوظائف التي تقبل العديد من القيم و أنواع كما هو معقول و الحفاظ على ضيقا جدا تعريف السلوك.هذا هو البديل من ما نادية كانت تتحدث عن.النظر في المسائل التالية الأعراف وظيفة الخاص بك:

  1. intersect_two_lists(None, None)
  2. intersect_two_lists([], ())
  3. intersect_two_lists('12', '23')
  4. intersect_two_lists([1, 2], {1: 'one', 2: 'two'})
  5. intersect_two_lists(False, [1])
  6. intersect_two_lists(None, [1])

أتوقع أن (5) يطرح استثناء منذ يمر False هو نوع الخطأ.بقية منهم ، ومع ذلك ، جعل نوعا من الشعور ولكن هذا يعتمد حقا على العقد أن تعمل الدول.إذا intersect_two_lists تم تعريفها العودة تقاطع اثنين iterables, ثم كل شيء آخر من (5) يجب أن تعمل طالما None صالح تمثيل مجموعة فارغة.تنفيذ سيكون شيئا مثل:

def intersect_two_lists(seq1, seq2):
    if seq1 is None: seq1 = []
    if seq2 is None: seq2 = []
    if not isinstance(seq1, collections.Iterable):
        raise TypeError("seq1 is not Iterable")
    if not isinstance(seq2, collections.Iterable):
        raise TypeError("seq1 is not Iterable")
    return filter(...)

أنا أكتب عادة وظائف المساعد التي تنفذ أيا كان العقد ثم ندعو لهم أن تحقق جميع شروط مسبقة.شيء من هذا القبيل:

def require_iterable(name, arg):
    """Returns an iterable representation of arg or raises an exception."""
    if arg is not None:
        if not isinstance(arg, collections.Iterable):
            raise TypeError(name + " is not Iterable")
        return arg
    return []

def intersect_two_lists(seq1, seq2):
    list1 = require_iterable("seq1", seq1)
    list2 = require_iterable("seq2", seq2)
    return filter(...)

يمكنك أيضا توسيع هذا المفهوم و تمر في "السياسة" كما اختياري الحجة.لا أنصح تفعل هذا إلا إذا كنت تريد أن تبني السياسة القائمة على التصميم.أردت أن أذكر ذلك فقط في حال كنت لم ينظر إلى هذا الخيار من قبل.

إذا كان العقد من أجل intersect_two_lists هو أنه لا يقبل إلا اثنين غير فارغة list المعلمات ، ثم تكون صريحة و رمي الاستثناءات إذا كان العقد:

def require_non_empty_list(name, var):
    if not isinstance(var, list):
        raise TypeError(name + " is not a list")
    if var == []:
        raise ValueError(name + " is empty")

def intersect_two_lists(list1, list2):
    require_non_empty_list('list1', list1)
    require_non_empty_list('list2', list2)
    return filter(...)

أعتقد أن المغزى من القصة هو مهما فعلت ذلك باستمرار تكون صريحة.شخصيا, أنا عادة ما يفضلون رفع الاستثناءات كلما العقد هو خرق أو أنا أعطيت القيمة التي أنا حقا لا يمكن استخدام.إذا كانت القيم التي أنا أعطيت معقولة ، ثم تحاول أن تفعل شيء معقول في المقابل.قد ترغب أيضا في قراءة C++ التعليمات لايت دخول على الاستثناءات.هذا إدخال معين يمنحك المزيد غذاء للفكر عن الاستثناءات.

على المجموعات (القوائم مجموعات ، dicts ، إلخ.) تعود فارغة جمع هو الخيار الواضح لأنه يسمح المكالمة الموقع المنطق أن تبقى واضحة دفاعية المنطق.أكثر صراحة فارغة جمع لا تزال جيدة تماما الإجابة من خلال وظيفة من الذي تتوقع مجموعة, ليس لديك للتأكد من أن النتيجة هي من أي نوع آخر ، يمكن أن تستمر منطق الأعمال في بيئة نظيفة الطريقة.

عدم جمع النتائج هناك عدة طرق للتعامل مع الشرطي العوائد:

  1. كما العديد من الإجابات سبق وشرحت ، استخدام الاستثناءات هي طريقة واحدة لحل هذه ، الاصطلاحية بيثون.ومع ذلك هو عدم تفضيل استخدام الاستثناءات على التحكم في التدفق كما أجد أنه يخلق غموض في نوايا استثناء.بدلا من رفع الاستثناءات الفعلية في حالات استثنائية.
  2. حل آخر هو العودة None بدلا من توقع النتيجة ولكن هذه القوات المستخدم لإضافة دفاعية الشيكات في كل مكان في المواقع ، تشويش الأعمال الفعلية المنطق يحاولون في الواقع تنفيذ.
  3. الطريق الثالث هو استخدام مجموعة النوع الذي هو الوحيد القادر على عقد عنصر واحد (أو صريح فارغة).ويسمى هذا اختياري و هو الأسلوب المفضل لأنه يسمح لك للحفاظ على نظافة الاتصال الموقع المنطق.غير أن الثعبان ليس لديها المدمج في نوع اختياري ، لذلك يمكنني استخدام بلدي.نشرت في مكتبة صغيرة تسمى optional.py إذا كان أي شخص يريد أن يعطي هو محاولة.يمكنك تثبيته باستخدام pip install optional.py.أرحب التعليقات ، طلبات ، الاشتراكات.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top