software - python tutorial pdf




किसी वस्तु के प्रकार का निर्धारण करें? (6)

क्या कोई वैरिएबल एक सूची, शब्दकोश, या कुछ और निर्धारित करने का एक आसान तरीका है? मुझे ऑब्जेक्ट वापस मिल रहा है जो कि या तो हो सकता है और मुझे अंतर बताने में सक्षम होना चाहिए।


एक पायथन ऑब्जेक्ट के प्रकार का निर्धारण करें

प्रकार के साथ किसी ऑब्जेक्ट के प्रकार का निर्धारण करें

>>> obj = object()
>>> type(obj)
<class 'object'>

हालांकि यह काम करता है, __class__ जैसे डबल अंडरस्कोर विशेषताओं से बचें - वे अर्थात् सार्वजनिक नहीं हैं, और, शायद इस मामले में नहीं, अंतर्निहित कार्यों में आमतौर पर बेहतर व्यवहार होता है।

>>> obj.__class__ # avoid this!
<class 'object'>

टाइपिंग टाइप करें

क्या कोई वैरिएबल एक सूची, शब्दकोश, या कुछ और निर्धारित करने का एक आसान तरीका है? मुझे ऑब्जेक्ट वापस मिल रहा है जो कि या तो हो सकता है और मुझे अंतर बताने में सक्षम होना चाहिए।

वैसे यह एक अलग सवाल है, प्रकार का उपयोग न करें - उपयोग isinstance :

def foo(obj):
    """given a string with items separated by spaces, 
    or a list or tuple, 
    do something sensible
    """
    if isinstance(obj, str):
        obj = str.split()
    return _foo_handles_only_lists_or_tuples(obj)

यह उस मामले को शामिल करता है जहां आपका उपयोगकर्ता स्ट्रक्सेज द्वारा कुछ चालाक या समझदार हो सकता है - लिस्कोव प्रतिस्थापन के सिद्धांत के अनुसार, आप अपने कोड को तोड़ने के बिना isinstance उदाहरणों का उपयोग करने में सक्षम होना चाहते हैं - और isinstance समर्थन करता है।

Abstractions का प्रयोग करें

इससे भी बेहतर, आप collections या numbers से एक विशिष्ट सार बेस क्लास की तलाश कर सकते हैं:

from collections import Iterable
from numbers import Number

def bar(obj):
    """does something sensible with an iterable of numbers, 
    or just one number
    """
    if isinstance(obj, Number): # make it a 1-tuple
        obj = (obj,)
    if not isinstance(obj, Iterable):
        raise TypeError('obj must be either a number or iterable of numbers')
    return _bar_sensible_with_iterable(obj)

या बस स्पष्ट रूप से टाइप-चेक न करें

या, शायद सबसे अच्छा, बतख-टाइपिंग का उपयोग करें, और स्पष्ट रूप से अपना कोड टाइप न करें। बतख-टाइपिंग अधिक लालित्य और कम verbosity के साथ Liskov प्रतिस्थापन का समर्थन करता है।

def baz(obj):
    """given an obj, a dict (or anything with an .items method) 
    do something sensible with each key-value pair
    """
    for key, value in obj.items():
        _baz_something_sensible(key, value)

निष्कर्ष

  • वास्तव में एक उदाहरण की कक्षा प्राप्त करने के लिए type का उपयोग करें।
  • वास्तविक उप-वर्गों या पंजीकृत अमूर्तताओं की स्पष्ट रूप से जांच करने के लिए isinstance का उपयोग करें।
  • और बस टाइप-चेकिंग से बचें जहां यह समझ में आता है।

आइंस्टेंस का उपयोग करके सावधान रहें

isinstance(True, bool)
True
>>> isinstance(True, int)
True

लेकिन टाइप करें

type(True) == bool
True
>>> type(True) == int
False

आप type() या isinstance() उपयोग कर सकते हैं।

>>> type([]) is list
True

चेतावनी दीजिये कि आप एक ही नाम के वर्तमान दायरे में एक चर निर्दिष्ट करके list या किसी अन्य प्रकार को पकड़ सकते हैं।

>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) 'aight'
>>> dict = "dude."
>>> t(the_d) 'NOPE'

ऊपर हम देखते हैं कि dict को एक स्ट्रिंग पर फिर से सौंप दिया जाता है, इसलिए परीक्षण:

type({}) is dict

... विफल रहता है।

इसके चारों ओर पाने के लिए और type() अधिक सावधानीपूर्वक उपयोग type() :

>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True

ऑब्जेक्ट के उदाहरणों पर आपके पास भी है:

__class__

विशेषता। यहां पाइथन 3.3 कंसोल से लिया गया एक नमूना है

>>> str = "str"
>>> str.__class__
<class 'str'>
>>> i = 2
>>> i.__class__
<class 'int'>
>>> class Test():
...     pass
...
>>> a = Test()
>>> a.__class__
<class '__main__.Test'>

सावधान रहें कि अजगर 3.x और न्यू-स्टाइल कक्षाओं में (वैकल्पिक रूप से पाइथन 2.6 से उपलब्ध) कक्षा और प्रकार विलय कर दिया गया है और यह कभी-कभी अप्रत्याशित परिणामों का कारण बन सकता है। मुख्य रूप से इस कारण से परीक्षण प्रकार / कक्षाओं का मेरा पसंदीदा तरीका कार्य में निर्मित isinstance लिए है।


पिछले उत्तरों के एक तरफ के रूप में, संग्रह.एबीसी के अस्तित्व का उल्लेख करने लायक है जिसमें कई अमूर्त आधार वर्ग (एबीसी) शामिल हैं जो बतख-टाइपिंग का पूरक हैं।

उदाहरण के लिए, स्पष्ट रूप से जांचने के बजाय कि कुछ सूची है या नहीं:

isinstance(my_obj, list)

आप कर सकते हैं, अगर आप केवल यह देखने में रूचि रखते हैं कि आपके पास ऑब्जेक्ट प्राप्त करने की वस्तु है, तो collections.abc.Sequence उपयोग करें collections.abc.Sequence :

from collections.abc import Sequence
isinstance(my_obj, Sequence) 

यदि आप उन वस्तुओं में सख्ती से रूचि रखते हैं जो वस्तुओं को प्राप्त करने, सेट करने और हटाने (यानी उत्परिवर्तनीय अनुक्रम) की अनुमति देते हैं, तो आप collections.abc.MutableSequence . abc.MutableSequence का चयन करेंगे।

कई अन्य एबीसी को परिभाषित किया गया है, वस्तुओं के लिए Mapping जिन्हें मानचित्र, Iterable , Iterable , और Iterable रूप में उपयोग किया जा सकता है। collections.abc लिए प्रलेखन में इन सभी की एक पूरी सूची देखी जा सकती है


यह try करने के लिए और अधिक Pythonic हो सकता है ... ब्लॉक except । इस तरह, यदि आपके पास ऐसी कक्षा है जो किसी सूची की तरह क्वैक करता है, या एक ताना की तरह क्वैक करता है, तो यह वास्तव में व्यवहार करेगा कि इसके प्रकार वास्तव में क्या है।

स्पष्टीकरण के लिए, परिवर्तनीय प्रकारों के बीच "अंतर बताते हुए" की पसंदीदा विधि डक टाइपिंग नामक कुछ चीज़ों के साथ होती है: जब तक कि वेरिएबल (और रिटर्न प्रकार) जो एक वैरिएबल प्रतिक्रिया देता है वह आपके सबराउटिन की अपेक्षा करता है, जैसा कि आप इसकी अपेक्षा करते हैं होने के लिए। उदाहरण के लिए, यदि आपके पास कक्षा है जो getattr और setattr साथ ब्रैकेट ऑपरेटरों को getattr setattr , लेकिन कुछ मजाकिया आंतरिक योजना का उपयोग करती है, तो यह एक शब्दकोश के रूप में व्यवहार करना उचित होगा यदि वह अनुकरण करने की कोशिश कर रहा है।

type(A) is type(B) साथ दूसरी समस्या type(A) is type(B) जांच है कि यदि A B उप-वर्ग है, तो यह प्रोग्राम के रूप में false होने पर मूल्यांकन करता है, तो आप उम्मीद करेंगे कि यह true होगा। यदि कोई ऑब्जेक्ट किसी सूची का उप-वर्ग है, तो उसे एक सूची की तरह काम करना चाहिए: दूसरे उत्तर में प्रस्तुत प्रकार की जांच करना इसे रोक देगा। (हालांकि, isinstance काम करेगा)।





python