كيف يمكنني نوع-التحقق من المتغيرات في الثعبان ؟

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

  •  19-08-2019
  •  | 
  •  

سؤال

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

أول رد فعل لي هو أن تفعل شيئا مثل هذا:

def isInteger(n):
    return int(n) == n

ولكن لا يسعني التفكير في أن هذا هو 1) تكلفة 2) القبيح و 3) تخضع تحت رحمة آلة ابسيلون.

لا بايثون توفر أي مواطن يعني من نوع التحقق من المتغيرات ؟ أو أن هذا يعتبر انتهاكا اللغة كتابة حيوي التصميم ؟

تحرير:لأن عددا من الناس قد طلب - طلب في السؤال يعمل مع IPv4 البادئات, مصادر البيانات من شقة ملفات نصية.إذا كان أي إدخال تحليل في تعويم ، هذا السجل يجب أن تعتبر تالف و تجاهلها.

هل كانت مفيدة؟

المحلول

isinstance(n, int)

إذا كنت بحاجة إلى معرفة ما إذا كان بالتأكيد الفعلية الباحث وليس فئة فرعية من الباحث (عموما لا يجب أن تفعل هذا):

type(n) is int

هذا:

return int(n) == n

ليست هذه فكرة جيدة, كما عبر نوع المقارنات يمكن أن يكون صحيحا - لا سيما int(3.0)==3.0

نصائح أخرى

نعم كما ايفان وقال: لا نوع الاختيار.مجرد محاولة استخدام القيمة:

def myintfunction(value):
   """ Please pass an integer """
   return 2 + value

أن لا يكون typecheck.هو أفضل بكثير!دعونا نرى ماذا يحدث عندما تجرب ذلك:

>>> myintfunction(5)
7

يعمل لأنه هو عدد صحيح.Hm.يتيح محاولة بعض النصوص.

>>> myintfunction('text')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in myintfunction
TypeError: unsupported operand type(s) for +: 'int' and 'str'

فإنه يدل على خطأ ، TypeError ، وهو ما ينبغي القيام به على أي حال.إذا كان المتصل يريد للقبض على ذلك ، فمن الممكن.

ماذا كنت ستفعل لو كنت فعلت typecheck?تظهر خطأ أليس كذلك ؟ حتى لا تضطر إلى typecheck لأن الخطأ هو بالفعل تظهر تلقائيا.

بالإضافة منذ كنت لم typecheck لديك وظيفة العمل مع أنواع أخرى:

يطفو:

>>> print myintfunction(2.2)
4.2

الأعداد المركبة:

>>> print myintfunction(5j)
(2+5j)

الكسور العشرية:

>>> import decimal
>>> myintfunction(decimal.Decimal('15'))
Decimal("17")

حتى تعسفية تماما الأشياء التي يمكن أن تضيف الأرقام!

>>> class MyAdderClass(object):
...     def __radd__(self, value):
...             print 'got some value: ', value
...             return 25
... 
>>> m = MyAdderClass()
>>> print myintfunction(m)
got some value:  2
25

إذن من الواضح أنك تحصل على شيء من typechecking.وتفقد الكثير.


تحديث:

منذ تحريرها السؤال, فمن الواضح الآن أن التطبيق الخاص بك يدعو بعض المنبع الروتين الذي يجعل الشعور فقط مع رجات.

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

ولكن...إذا كان المنبع وظيفة سوف تتصرف بشكل غير صحيح و قتل بعض الأطفال إذا كنت تمر تعوم (ما زلت اشك فى ذلك) ، ثم فقط فقط اتصل int() على ذلك:

def myintfunction(value):
   """ Please pass an integer """
   return upstreamfunction(int(value))

كنت لا تزال لا typechecking, حتى تحصل على معظم فوائد لا typechecking.


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

assert isinstance(...)
assert type() is xxxx

بهذه الطريقة يمكننا إيقاف asserts وإزالة هذا <sarcasm>ميزة</sarcasm> من البرنامج من خلال الاتصال على أنها

python -OO program.py
if type(n) is int

هذا يتحقق إذا n هو الثعبان الباحث ، فقط int.لن تقبل فرعية من int.

نوع التحقق ومع ذلك لا يصلح "بيثون الطريق".يمكنك استخدام أفضل n كما int, وإذا كان يطرح استثناء ، قبض عليه والعمل به.

بيثون يدعم الآن التدريجي الكتابة عبر كتابة وحدة و mypy.على typing الوحدة هي جزء من stdlib من بيثون 3.5 و يمكن تحميلها من PyPi إذا كنت بحاجة إلى backports بايثون 2 أو إصدار سابق من بيثون 3.يمكنك تثبيت mypy عن طريق تشغيل pip install mypy من سطر الأوامر.

باختصار, إذا كنت ترغب في التحقق من أن بعض من وظيفة يأخذ في الباحث ، تعويم ، وإرجاع سلسلة, كنت الحواشي الدالة كما يلي:

def foo(param1: int, param2: float) -> str:
    return "testing {0} {1}".format(param1, param2)

إذا كان لديك ملف اسمه test.py, يمكنك أن ثم typecheck بمجرد تثبيت mypy عن طريق تشغيل mypy test.py من سطر الأوامر.

إذا كنت تستخدم نسخة قديمة من الثعبان دون دعم وظيفة الشروح ، يمكنك استخدام نوع التعليقات لتحقيق نفس التأثير:

def foo(param1, param2):
    # type: (int, float) -> str
    return "testing {0} {1}".format(param1, param2)

يمكنك استخدام نفس الأمر mypy test.py لبيثون 3 ملفات ، mypy --py2 test.py بايثون 2 الملفات.

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

إذا لسبب ما كنت في حاجة إلى أنواع لفحصها في وقت التشغيل (ربما تحتاج إلى التحقق من صحة الكثير من مدخلات؟), يجب عليك اتباع النصائح الواردة في إجابات أخرى -- على سبيل المثالاستخدام isinstance, issubclass, و مثل.هناك أيضا بعض المكتبات مثل فرض أن محاولة تنفيذ typechecking (احترام نوع الشروح) في وقت التشغيل, على الرغم من أنني غير مؤكد كيف الإنتاج جاهزة فهي من وقت كتابة هذا التقرير.

لمزيد من المعلومات و التفاصيل ، انظر mypy الموقع, ، mypy التعليمات, ، بيب 484.

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

class MyInt(int):
    # ... extra stuff ...

البرمجة بايثون وأداء typechecking كما قد تكون في اللغات الأخرى لا يبدو مثل اختيار مفك إلى ضرب مسمار في مع.هو أكثر أناقة استخدام بايثون معالجة الاستثناء الميزات.

من تفاعلية سطر الأوامر, يمكنك تشغيل بيان مثل:

int('sometext')

من شأنها أن تولد خطأ - ipython يقول لي:

<type 'exceptions.ValueError'>: invalid literal for int() with base 10: 'sometext'

الآن يمكنك كتابة بعض التعليمات البرمجية مثل:

try:
   int(myvar) + 50
except ValueError:
   print "Not a number"

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

أود أن يميل إلى شيء من هذا القبيل:

def check_and_convert(x):
    x = int(x)
    assert 0 <= x <= 255, "must be between 0 and 255 (inclusive)"
    return x

class IPv4(object):
    """IPv4 CIDR prefixes is A.B.C.D/E where A-D are 
       integers in the range 0-255, and E is an int 
       in the range 0-32."""

    def __init__(self, a, b, c, d, e=0):
        self.a = check_and_convert(a)
        self.b = check_and_convert(a)
        self.c = check_and_convert(a)
        self.d = check_and_convert(a)
        assert 0 <= x <= 32, "must be between 0 and 32 (inclusive)"
        self.e = int(e)

بهذه الطريقة عندما كنت تستخدم أي شيء يمكن أن تنتقل بعد فقط مخزن صالح صحيح.

ماذا عن:

def ip(string):
    subs = string.split('.')
    if len(subs) != 4:
        raise ValueError("incorrect input")
    out = tuple(int(v) for v in subs if 0 <= int(v) <= 255)
    if len(out) != 4:
        raise ValueError("incorrect input")
    return out

طبعا هناك معيار isinstance(3, int) وظيفة ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top