ما الكنسي طريقة للتحقق من نوع الثعبان ؟

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

  •  02-07-2019
  •  | 
  •  

سؤال

ما هي أفضل طريقة للتحقق من ما إذا كان الكائن هو من نوع معين?حول كيفية التحقق من ما إذا كان كائن يرث من نوع معين?

دعونا نقول لدي كائن o.كيف يمكنني التحقق من ما إذا كان هو str?

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

المحلول

للتحقق مما إذا o هو مثيل str أو أي فئة فرعية من str, استخدام isinstance (هذا من شأنه أن يكون "canonical" الطريق):

if isinstance(o, str):

للتحقق إذا كان نوع من o هو بالضبط str (استبعاد الفئات الفرعية):

if type(o) is str:

التالية أيضا يعمل و يمكن أن تكون مفيدة في بعض الحالات:

if issubclass(type(o), str):

انظر المدمج في وظائف في بيثون مكتبة مرجعية المعلومات ذات الصلة.

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

if isinstance(o, basestring):

لأن هذا سوف أيضا التقاط سلاسل Unicode (unicode هو فئة فرعية من str;سواء str و unicode والفئات الفرعية من basestring).علما بأن basestring لم يعد موجودا في بيثون 3 ، حيث هناك الفصل الصارم من سلاسل (str) و البيانات الثنائية (bytes).

بدلا من ذلك ، isinstance تقبل tuple من الطبقات.هذا سوف ترجع True إذا كان x هو مثيل من أي فئة فرعية من أي من (str, unicode):

if isinstance(o, (str, unicode)):

نصائح أخرى

على معظم Pythonic طريقة للتحقق من نوع كائن...لا التحقق من ذلك.

منذ الثعبان تشجع بطة الكتابة, عليك فقط try...except استخدام أساليب الكائن بالطريقة التي تريد استخدامها.حتى إذا كان لديك وظيفة تبحث عن للكتابة ملف الكائن ، لا تحقق من أنه من فئة فرعية من file, فقط حاول استخدام .write() الطريقة!

بالطبع في بعض الأحيان هذه لطيفة تجريدات كسر ، isinstance(obj, cls) هو ما تحتاجه.ولكن استخدام لماما.

isinstance(o, str) سيعود True إذا o هو str أو هو من النوع الذي يرث من str.

type(o) is str سيعود True إذا وفقط إذا o هو str.فإنه سيعود False إذا o هو من النوع الذي يرث من str.

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

def foo(i: int):
    return i

foo(5)
foo('oops')

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

واحد من هذه البرامج الأخرى التي يمكن استخدامها للعثور على نوع الخطأ mypy:

mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"

(قد تحتاج إلى تثبيت mypy من مدير الحزم.أنا لا أعتقد أنه يأتي مع CPython ولكن يبدو أن بعض مستوى من "officialness".)

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

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

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

على typing الحزمة توفر نوع المتغيرات التي يمكن استخدامها في نوع تلميحات للتعبير عن حاجة السلوكيات دون الحاجة إلى أنواع معينة.على سبيل المثال, ويشمل المتغيرات مثل Iterable و Callable للحصول على تلميحات إلى تحديد الحاجة إلى أي نوع مع تلك السلوكيات.

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

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

class Bomb:
    def __init__(self):
        ""

    def talk(self):
        self.explode()

    def explode(self):
        print "BOOM!, The bomb explodes."

class Duck:
    def __init__(self):
        ""
    def talk(self):
        print "I am a duck, I will not blow up if you ask me to talk."    

class Kid:
    kids_duck = None

    def __init__(self):
        print "Kid comes around a corner and asks you for money so he could buy a duck."

    def takeDuck(self, duck):
        self.kids_duck = duck
        print "The kid accepts the duck, and happily skips along"

    def doYourThing(self):
        print "The kid tries to get the duck to talk"
        self.kids_duck.talk()

myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()
isinstance(o, str)

رابط مستندات

أعتقد أن الشيء باردة حول استخدام لغة ديناميكية مثل الثعبان هو أنت حقا لا يجب أن تحقق شيء من هذا القبيل.

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

لقد استعملت هذا كثيرا عند الحصول على البيانات من الإنترنت مع urllib2.urlopen() والتي ترجع ملف مثل الكائن.هذا بدوره يمكن أن تنتقل إلى أي أسلوب أن يقرأ من ملف ، لأنه ينفذ نفس read() طريقة حقيقية الملف.

ولكن أنا متأكد من أن هناك وقت ومكان باستخدام isinstance(), وإلا فإنه على الأرجح لن تكون هناك :)

إلى هوغو:

ربما يعني list بدلا من array, لكن هذا يشير إلى المشكلة برمتها مع نوع فحص - أنت لا تريد أن تعرف إذا كان الكائن في السؤال هي قائمة, كنت تريد أن تعرف إذا كان نوعا من التسلسل أو إذا كان كائن واحد.وذلك في محاولة لاستخدام مثل التسلسل.

ويقول كنت ترغب في إضافة الكائن إلى القائمة تسلسل ، أو إذا كان تسلسل الكائنات ، إضافة كل منهم

try:
   my_sequence.extend(o)
except TypeError:
  my_sequence.append(o)

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

وعادة ما تختار تصميم لي API بحيث لا يقبل إلا إما قيمة واحدة أو تسلسل يجعل الأمور أسهل.ليس من الصعب وضع [ ] حول قيمة واحدة عند تمرير ذلك في حال الضرورة.

(على الرغم من أن هذا يمكن أن يسبب أخطاء مع سلاسل, كما أنها لا تبدو مثل (هي) متواليات.)

لمزيد من نوع معقد التصديقات أحب typeguard'النهج التحقق من صحة بناء على نوع الثعبان تلميح الشروح:

from typeguard import check_type
from typing import List

try:
    check_type('mylist', [1, 2], List[int])
except TypeError as e:
    print(e)

يمكنك إجراء معقد جدا التصديقات في نظيفة جدا للقراءة الموضة.

check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo) 

يمكنك التحقق من تحت خط للتحقق من أي نوع الحرف قيمة معينة هي:

def chr_type(chrx):
    if chrx.isalpha()==True:
        return 'alpha'
    elif chrx.isdigit()==True:
        return 'numeric'
    else:
        return 'nothing'

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