पायथन फ़ंक्शंस किस प्रकार के मापदंडों को संभालते हैं जो आप पास करते हैं?


305

जब तक मैं गलत नहीं हूँ, पायथन में एक समारोह बनाना इस तरह काम करता है:

def my_func(param1, param2):
    # stuff

हालाँकि, आप वास्तव में उन मापदंडों के प्रकार नहीं देते हैं। इसके अलावा, अगर मुझे याद है, पायथन एक जोरदार टाइप की गई भाषा है, तो, ऐसा लगता है जैसे पायथन को आपको फ़ंक्शन क्रिएटर की अपेक्षा भिन्न प्रकार के पैरामीटर में पास नहीं होने देना चाहिए। हालांकि, पायथन कैसे जानता है कि फ़ंक्शन का उपयोगकर्ता उचित प्रकारों में गुजर रहा है? यदि प्रोग्राम गलत तरीके से पैरामीटर का उपयोग करता है, तो क्या यह गलत प्रकार है, तो क्या कार्यक्रम मर जाएगा? क्या आपको प्रकार निर्दिष्ट करना है?


15
मुझे लगता है कि इस सवाल का स्वीकृत जवाब उन मौजूदा क्षमताओं के साथ अधिक अपडेट होना चाहिए जो पायथन पेश करता है। मुझे लगता है कि यह जवाब काम करता है।
code_dredd 21

जवाबों:


172

पाइथन दृढ़ता से टाइप किया गया है क्योंकि हर वस्तु का एक प्रकार है, प्रत्येक वस्तु अपने प्रकार को जानती है , यह गलती से या जानबूझकर किसी प्रकार की वस्तु का उपयोग करना असंभव है "जैसे कि" यह एक अलग प्रकार की वस्तु थी , और वस्तु पर सभी प्राथमिक ऑपरेशन हैं इसके प्रकार के लिए प्रत्यायोजित।

इसका नामों से कोई लेना-देना नहीं है । पायथन में एक नाम "एक प्रकार" नहीं है: यदि और जब किसी नाम को परिभाषित किया जाता है, तो नाम एक ऑब्जेक्ट को संदर्भित करता है , और ऑब्जेक्ट में एक प्रकार होता है (लेकिन यह वास्तव में नाम पर एक प्रकार को बाध्य नहीं करता है : a नाम एक नाम है)।

अजगर में एक नाम पूरी तरह से अलग-अलग समय पर अलग-अलग वस्तुओं को संदर्भित कर सकता है (जैसा कि अधिकांश प्रोग्रामिंग भाषाओं में, हालांकि सभी नहीं) - और इस तरह के नाम पर कोई बाधा नहीं है, अगर यह एक बार टाइप एक्स के एक ऑब्जेक्ट को संदर्भित करता है, यह तो सर्वदा पर प्रकार एक्स प्रतिबन्ध का अन्य वस्तुओं के लिए एक ही उल्लेख करने के लिए विवश है नाम , "मजबूत टाइपिंग" की अवधारणा का हिस्सा नहीं हैं, हालांकि के कुछ उत्साही स्थिर टाइपिंग (जहां नाम है विवश हो, और एक स्थिर में, उर्फ compile- समय, फैशन, भी) इस तरह से शब्द का दुरुपयोग करते हैं।


71
तो ऐसा लगता है कि मजबूत टाइपिंग इतना मजबूत नहीं है, इस विशेष मामले में, यह स्थिर टाइपिंग से कमजोर है। समय, नाम / चर / संदर्भ पर संकलन टाइपिंग बाधा वास्तव में काफी महत्वपूर्ण है, इसलिए मैं साहसपूर्वक दावा करता हूं कि स्टेटिक टाइपिंग के रूप में अजगर अच्छा नहीं है इस पहलू पर। कृपया मुझे सुधारें अगर मैं गलत हूं।
लिआंग

19
@liang यह एक राय है, इसलिए आप सही या गलत नहीं हो सकते। यह निश्चित रूप से मेरी राय है, और मैंने कई भाषाओं की कोशिश की है। यह तथ्य कि मैं मापदंडों के प्रकार (और इस प्रकार सदस्यों) का पता लगाने के लिए अपनी आईडीई का उपयोग नहीं कर सकता, अजगर का एक बड़ा दोष है। यदि यह कमी डक टाइपिंग के फायदों से अधिक महत्वपूर्ण है, तो आप जिस व्यक्ति से पूछते हैं, उस पर निर्भर करता है।
Maarten Bodewes

6
लेकिन यह किसी भी प्रश्न का उत्तर नहीं देता है: "हालांकि, पायथन को कैसे पता चलता है कि फ़ंक्शन का उपयोगकर्ता उचित प्रकारों में गुजर रहा है? क्या प्रोग्राम केवल मर जाएगा यदि यह गलत प्रकार है, मान लें कि फ़ंक्शन वास्तव में पैरामीटर का उपयोग करता है? क्या आपको प्रकार निर्दिष्ट करना है? " या ..
qPCR4vir

4
@ qPCR4vir, किसी भी वस्तु को एक तर्क के रूप में पारित किया जा सकता है। त्रुटि (एक अपवाद, प्रोग्राम "मर" नहीं जाएगा यदि इसे पकड़ने के लिए कोड किया गया है, तो देखें try/ except) तब होगा जब एक ऑपरेशन का प्रयास किया जाता है कि ऑब्जेक्ट समर्थन नहीं करता है। पायथन 3.5 में, अब आप वैकल्पिक रूप से तर्कों के "प्रकार निर्दिष्ट कर सकते हैं", लेकिन कोई त्रुटि नहीं होती है, प्रति से, अगर कल्पना का उल्लंघन होता है; टाइपिंग नोटेशन केवल अलग-अलग उपकरणों की मदद करने के लिए है जो विश्लेषण आदि करते हैं, यह स्वयं पायथन के व्यवहार को नहीं बदलता है।
एलेक्स मार्टेली

2
@AlexMartelli। धन्यवाद! मेरे लिए यह सही उत्तर है: "त्रुटि (एक अपवाद, प्रोग्राम" मर नहीं जाएगा "यदि इसे पकड़ने के लिए कोडित किया गया है, तो प्रयास देखें / छोड़कर) .."
qPCR4vir

753

अन्य उत्तरों ने बत्तख टाइपिंग और tzot द्वारा सरल उत्तर की व्याख्या करने में अच्छा काम किया है :

अजगर के पास अन्य भाषाओं की तरह चर नहीं होते हैं, जहां चर का एक प्रकार और एक मूल्य होता है; इसमें वस्तुओं को इंगित करने वाले नाम हैं, जो उनके प्रकार को जानते हैं।

हालांकि , 2010 के बाद से एक दिलचस्प बात बदल गई है (जब सवाल पहले पूछा गया था), अर्थात् पीईपी 3107 का कार्यान्वयन (पायथन 3 में लागू)। अब आप वास्तव में एक पैरामीटर के प्रकार और फ़ंक्शन के रिटर्न प्रकार को इस तरह निर्दिष्ट कर सकते हैं:

def pick(l: list, index: int) -> int:
    return l[index]

हम यहां देख सकते हैं कि pick2 पैरामीटर, एक सूची lऔर एक पूर्णांक लेता हैindex । इसे एक पूर्णांक भी वापस करना चाहिए।

इसलिए यहां यह निहित है कि lपूर्णांकों की एक सूची है जिसे हम बिना अधिक प्रयास के देख सकते हैं, लेकिन अधिक जटिल कार्यों के लिए यह थोड़ा भ्रमित हो सकता है कि सूची में क्या होना चाहिए। हम भी चाहते हैं कि डिफ़ॉल्ट मान index0 हो। इसे हल करने के लिए आप pickइसके बजाय इस तरह लिखना पसंद कर सकते हैं :

def pick(l: "list of ints", index: int = 0) -> int:
    return l[index]

ध्यान दें कि अब हम एक स्ट्रिंग में टाइप के रूप में डालते हैं l , जो कि वाक्यात्मक रूप से अनुमत है, लेकिन यह प्रोग्रामेटिक रूप से पार्स करने के लिए अच्छा नहीं है (जो हम बाद में वापस आएंगे)।

यह ध्यान रखना महत्वपूर्ण है कि TypeErrorयदि आप फ्लोट पास करते हैं तो पायथन को नहीं उठाया जाएगा index, इसका कारण पायथन के डिजाइन दर्शन में मुख्य बिंदुओं में से एक है: "हम यहाँ सभी वयस्कों की सहमति दे रहे हैं" , जिसका अर्थ है कि आपसे उम्मीद की जाती है इस बात से अवगत रहें कि आप एक समारोह में क्या कर सकते हैं और क्या नहीं। यदि आप वास्तव में ऐसा कोड लिखना चाहते हैं जो TypeErrors फेंकता है, तो आप isinstanceफ़ंक्शन का उपयोग यह जांचने के लिए कर सकते हैं कि पारित तर्क उचित प्रकार का है या इस तरह का एक उपवर्ग:

def pick(l: list, index: int = 0) -> int:
    if not isinstance(l, list):
        raise TypeError
    return l[index]

इस पर अधिक कि आपको शायद ही ऐसा क्यों करना चाहिए और इसके बजाय आपको क्या करना चाहिए, इसके बारे में अगले भाग और टिप्पणियों में बात की गई है।

PEP 3107 न केवल कोड पठनीयता में सुधार करता है, बल्कि इसके कई फिटिंग उपयोग के मामले भी हैं जिन्हें आप यहाँ पढ़ सकते हैं ।


PEP 484 की शुरूआत के साथ Python 3.5 में टाइप एनोटेशन पर बहुत अधिक ध्यान दिया गया जो टाइप संकेत के लिए एक मानक मॉड्यूल का परिचय देता है।

ये प्रकार के संकेत टाइप चेकर mypy ( GitHub ) से आए थे , जो अब PEP 484 अनुरूप है।

टाइपिंग मॉड्यूल के साथ टाइप संकेत के एक बहुत व्यापक संग्रह के साथ आता है, जिसमें शामिल हैं:

  • List, Tuple, Set, Map- के लिए list, tuple, setऔर mapक्रमशः।
  • Iterable - जनरेटर के लिए उपयोगी।
  • Any - जब यह कुछ भी हो सकता है।
  • Union- जब यह प्रकार के एक निर्धारित सेट के भीतर कुछ भी हो सकता है, जैसा कि विरोध किया गया है Any
  • Optional- जब यह कोई नहीं हो सकता है। के लिए आशुलिपि Union[T, None]
  • TypeVar - जेनेरिक के साथ प्रयोग किया जाता है।
  • Callable - मुख्य रूप से फ़ंक्शंस के लिए उपयोग किया जाता है, लेकिन अन्य कॉलबल्स के लिए इस्तेमाल किया जा सकता है।

ये सबसे आम प्रकार के संकेत हैं। टाइपिंग मॉड्यूल के लिए प्रलेखन में एक पूरी सूची पाई जा सकती है ।

टाइपिंग मॉड्यूल में शुरू की गई एनोटेशन विधियों का उपयोग करने का पुराना उदाहरण यहां दिया गया है:

from typing import List

def pick(l: List[int], index: int) -> int:
    return l[index]

एक शक्तिशाली विशेषता यह है Callableकि आप एनोटेट विधियों को टाइप करने की अनुमति देते हैं जो एक फ़ंक्शन को तर्क के रूप में लेते हैं। उदाहरण के लिए:

from typing import Callable, Any, Iterable

def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
    """An immediate version of map, don't pass it any infinite iterables!"""
    return list(map(f, l))

उपरोक्त उदाहरण के TypeVarबजाय के उपयोग के साथ और अधिक सटीक हो सकता है Any, लेकिन यह पाठक के लिए एक अभ्यास के रूप में छोड़ दिया गया है क्योंकि मेरा मानना ​​है कि मैं पहले से ही टाइपिंग द्वारा सक्षम अद्भुत नई सुविधाओं के बारे में बहुत अधिक जानकारी के साथ अपना जवाब भर चुका हूं।


पहले जब एक उदाहरण के लिए स्फिंक्स के साथ पाइथन कोड का दस्तावेजीकरण किया गया था , तो उपरोक्त कार्यक्षमता में से कुछ को इस तरह से प्रारूपित लेखन द्वारा प्राप्त किया जा सकता है:

def pick(l, index):
    """
    :param l: list of integers
    :type l: list
    :param index: index at which to pick an integer from *l*
    :type index: int
    :returns: integer at *index* in *l*
    :rtype: int
    """
    return l[index]

जैसा कि आप देख सकते हैं, यह कई अतिरिक्त लाइनें लेता है (सटीक संख्या इस बात पर निर्भर करती है कि आप कितना स्पष्ट होना चाहते हैं और आप अपने डॉकस्ट्रिंग को कैसे प्रारूपित करते हैं)। लेकिन अब यह आपके लिए स्पष्ट होना चाहिए कि PEP 3107 एक विकल्प प्रदान करता है जो कई (सभी?) तरीकों से बेहतर है। यह पीईपी 484 के साथ संयोजन में विशेष रूप से सच है , जैसा कि हमने देखा है, एक मानक मॉड्यूल प्रदान करता है जो इन प्रकार के संकेत / एनोटेशन के लिए एक वाक्यविन्यास को परिभाषित करता है जिसे इस तरह से इस्तेमाल किया जा सकता है कि यह अस्पष्ट और सटीक है लेकिन अभी तक लचीला है, के लिए बना रहा है। शक्तिशाली संयोजन।

मेरी निजी राय में, यह पायथन में अब तक की सबसे बड़ी विशेषताओं में से एक है। मैं लोगों को इसकी शक्ति का उपयोग शुरू करने के लिए इंतजार नहीं कर सकता। लंबे उत्तर के लिए क्षमा करें, लेकिन यह तब होता है जब मैं उत्तेजित हो जाता हूं।


पायथन कोड का एक उदाहरण जो भारी रूप से टाइपिंग का उपयोग करता है यहां पाया जा सकता है


2
@rickfoosusa: मुझे संदेह है कि आप पायथन 3 नहीं चला रहे हैं जिसमें यह सुविधा जोड़ी गई थी।
इरब

26
एक मिनट रुकिए! यदि परिभाषित करने वाला पैरामीटर और रिटर्न प्रकार एक नहीं बढ़ाता है TypeError, pick(l: list, index: int) -> intतो एक-लाइन को परिभाषित करने की तरह उपयोग करने का क्या मतलब है ? या मुझे यह गलत लगा, मुझे नहीं पता।
एरडिन एरे

24
@ ईरे एरडिन: यह एक आम गलतफहमी है और एक बुरे सवाल पर नहीं। इसका उपयोग प्रलेखन उद्देश्यों के लिए किया जा सकता है, आईडीई बेहतर ऑटोकंप्लीशन करने में मदद करता है और स्थैतिक विश्लेषण का उपयोग करके रनटाइम से पहले त्रुटियों को ढूंढता है (ठीक उसी तरह जैसे मैं जवाब में उल्लेख किया था)। ऐसी उम्मीदें हैं कि रनटाइम जानकारी का लाभ उठा सकता है और वास्तव में कार्यक्रमों को गति दे सकता है लेकिन इसे लागू होने में बहुत समय लगने वाला है। आप हो सकता है यह भी एक डेकोरेटर कि (सूचना में संग्रहित है आप के लिए TypeErrors फेंकता बनाने में सक्षम हो __annotations__समारोह वस्तु की विशेषता)।
एरब

2
@ErdinEray मुझे यह जोड़ना चाहिए कि TypeErrors को फेंकना एक बुरा विचार है (डिबगिंग कभी भी मज़ेदार नहीं है, चाहे कितनी भी अच्छी तरह से इच्छित अपवाद उठाए गए हों)। लेकिन डरो मत, मेरे जवाब में वर्णित नई सुविधाओं का लाभ बेहतर तरीके से सक्षम बनाता है: रनटाइम पर किसी भी चेकिंग पर भरोसा न करें, रनटाइम से आगे सब कुछ करें या एक संपादक का उपयोग करें जो आपके लिए स्थैतिक विश्लेषण करता है जैसे कि PyCharm ।
इरब

2
@Tony: जब आप दो और वापसी या आप वास्तव में एक टपल लौट वस्तुओं, ताकि आप टपल प्रकार एनोटेशन का उपयोग करना चाहिए, यानीdef f(a) -> Tuple[int, int]:
ERB

14

आप एक प्रकार निर्दिष्ट नहीं करते हैं। यह विधि केवल (रनटाइम पर) विफल होगी यदि यह उन विशेषताओं तक पहुंचने का प्रयास करता है जो कि पारित किए गए मापदंडों पर परिभाषित नहीं हैं।

तो यह सरल कार्य:

def no_op(param1, param2):
    pass

... कोई बात नहीं विफल हो जाएगा क्या दो args में पारित कर रहे हैं।

हालाँकि, यह फ़ंक्शन:

def call_quack(param1, param2):
    param1.quack()
    param2.quack()

... रनटाइम पर विफल हो जाएगा param1और अगर param2दोनों के पास कॉल करने योग्य गुण नहीं हैं quack


+1: विशेषताओं और विधियों को सांख्यिकीय रूप से निर्धारित नहीं किया जाता है। इस "उचित प्रकार" या "गलत प्रकार" की अवधारणा फ़ंक्शन द्वारा ठीक से काम करती है या नहीं, इसकी स्थापना कैसे की जाती है।
एस.लॉट

11

कई भाषाओं में चर होते हैं, जो एक विशिष्ट प्रकार के होते हैं और उनका मूल्य होता है। अजगर के पास चर नहीं हैं; इसमें ऑब्जेक्ट्स हैं, और आप इन ऑब्जेक्ट्स को संदर्भित करने के लिए नामों का उपयोग करते हैं।

अन्य भाषाओं में, जब आप कहते हैं:

a = 1

तब (आमतौर पर पूर्णांक) चर अपनी सामग्री को मूल्य 1 में बदल देता है।

पायथन में,

a = 1

इसका मतलब है "नाम का उपयोग एक वस्तु का उल्लेख करने के 1 "। आप एक इंटरैक्टिव पायथन सत्र में निम्नलिखित कर सकते हैं:

>>> type(1)
<type 'int'>

फ़ंक्शन typeको ऑब्जेक्ट के साथ कहा जाता है 1; चूंकि हर वस्तु अपने प्रकार को जानती है, इसलिए यह typeकहा जाना आसान है कि वह किस प्रकार का है और उसे वापस लौटा सकती है।

इसी तरह, जब भी आप किसी फ़ंक्शन को परिभाषित करते हैं

def funcname(param1, param2):

फ़ंक्शन दो ऑब्जेक्ट्स प्राप्त करता है, और उनके प्रकारों की परवाह किए बिना, param1और उन्हें नाम देता है param2। यदि आप यह सुनिश्चित करना चाहते हैं कि प्राप्त की गई वस्तुएँ एक विशिष्ट प्रकार की हैं, तो अपने फ़ंक्शन को इस तरह से कोड करें जैसे कि वे आवश्यक प्रकार के हैं और यदि वे नहीं हैं तो अपवादों को पकड़ लें। फेंके गए अपवाद आम तौर पर TypeError(आपने एक अमान्य ऑपरेशन का उपयोग किया है) और AttributeError(आपने एक अक्षम सदस्य तक पहुंचने का प्रयास किया है (विधियाँ भी सदस्य हैं))।


8

स्थिर या संकलन-समय प्रकार की जाँच के अर्थ में पायथन दृढ़ता से टाइप नहीं किया गया है।

अधिकांश पायथन कोड तथाकथित "बत्तख टाइपिंग" के अंतर्गत आता है - उदाहरण के लिए, आप readकिसी ऑब्जेक्ट पर एक विधि की तलाश करते हैं - आपको परवाह नहीं है कि क्या ऑब्जेक्ट डिस्क या सॉकेट पर एक फ़ाइल है, तो आप सिर्फ एन पढ़ना चाहते हैं इससे बाइट होती है।


21
अजगर को दृढ़ता से टाइप किया गया है। यह भी गतिशील रूप से टाइप किया गया है।
डैनियल न्यूबी

1
लेकिन यह किसी भी प्रश्न का उत्तर नहीं देता है: "हालांकि, पायथन को कैसे पता चलता है कि फ़ंक्शन का उपयोगकर्ता उचित प्रकारों में गुजर रहा है? क्या प्रोग्राम केवल मर जाएगा यदि यह गलत प्रकार है, मान लें कि फ़ंक्शन वास्तव में पैरामीटर का उपयोग करता है? क्या आपको प्रकार निर्दिष्ट करना है? " या ..
qPCR4vir

6

जैसा कि एलेक्स मार्टेली बताते हैं ,

सामान्य, पाइथोनिक, पसंदीदा समाधान लगभग हमेशा "बतख टाइपिंग" है: तर्क का उपयोग करने की कोशिश करें जैसे कि यह एक निश्चित वांछित प्रकार का था, इसे एक कोशिश में करें / बयान को छोड़कर सभी अपवादों को पकड़ने वाला हो सकता है यदि तर्क वास्तव में नहीं था। उस प्रकार के (या किसी अन्य प्रकार के अच्छी तरह से बत्तख का बच्चा; यह;; और खंड को छोड़कर, कुछ और प्रयास करें (तर्क का उपयोग करके) जैसे कि "यह किसी और प्रकार का था"।

उपयोगी जानकारी के लिए उनके बाकी पोस्ट पढ़ें।


5

पायथन परवाह नहीं करता है कि आप अपने कार्यों में क्या पास करते हैं। जब आप कॉल करते हैं my_func(a,b), तो param1 और param2 चर तब a और b के मानों को धारण करेंगे। पायथन को पता नहीं है कि आप फ़ंक्शन को उचित प्रकारों के साथ बुला रहे हैं, और प्रोग्रामर से अपेक्षा करता है कि वह ध्यान रखे। यदि आपके फ़ंक्शन को विभिन्न प्रकार के मापदंडों के साथ बुलाया जाएगा, तो आप कोड को ब्लॉक / को छोड़कर उन तक पहुँचने के साथ कोड लपेट सकते हैं और जो भी आप चाहते हैं उसमें मापदंडों का मूल्यांकन कर सकते हैं।


11
अजगर के पास अन्य भाषाओं की तरह चर नहीं होते हैं, जहां चर का एक प्रकार और एक मूल्य होता है; इसमें वस्तुओं को इंगित करने वाले नाम हैं , जो उनके प्रकार को जानते हैं।
tzot

2

आप कभी भी प्रकार निर्दिष्ट नहीं करते हैं; अजगर को बतख टाइपिंग की अवधारणा है ; मूल रूप से कोड जो मापदंडों को संसाधित करता है, उनके बारे में कुछ धारणाएं बनाएंगे - शायद कुछ तरीकों को कॉल करके जो पैरामीटर को लागू करने की उम्मीद है। यदि पैरामीटर गलत प्रकार का है, तो एक अपवाद फेंक दिया जाएगा।

सामान्य तौर पर यह आपके कोड पर निर्भर करता है कि आप उचित प्रकार की वस्तुओं के आसपास से गुजर रहे हैं - समय से पहले इसे लागू करने के लिए कोई संकलक नहीं है।


2

इस पृष्ठ पर उल्लेख के लायक डक-टाइपिंग से एक कुख्यात अपवाद है।

जब strफ़ंक्शन __str__वर्ग विधि को कॉल करता है तो वह अपने प्रकार को सूक्ष्मता से जाँचता है:

>>> class A(object):
...     def __str__(self):
...         return 'a','b'
...
>>> a = A()
>>> print a.__str__()
('a', 'b')
>>> print str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __str__ returned non-string (type tuple)

जैसे कि गुइडो हमें संकेत देता है कि एक अप्रत्याशित प्रकार का सामना करने पर एक कार्यक्रम को किस अपवाद को उठाना चाहिए।


1

अजगर में हर चीज का एक प्रकार होता है। एक पायथन फ़ंक्शन कुछ भी करेगा उसे यह करने के लिए कहा जाता है यदि प्रकार के तर्क इसका समर्थन करते हैं।

उदाहरण: एड के बारे में fooसब कुछ जोड़ देगा __add__;) इसके प्रकार के बारे में ज्यादा चिंता किए बिना। तो इसका मतलब है कि, विफलता से बचने के लिए, आपको केवल उन चीजों को प्रदान करना चाहिए जो अतिरिक्त समर्थन करते हैं।

def foo(a,b):
    return a + b

class Bar(object):
    pass

class Zoo(object):
    def __add__(self, other):
        return 'zoom'

if __name__=='__main__':
    print foo(1, 2)
    print foo('james', 'bond')
    print foo(Zoo(), Zoo())
    print foo(Bar(), Bar()) # Should fail

1

मैंने अन्य उत्तरों में इसका उल्लेख नहीं किया है, इसलिए मैं इसे बर्तन में जोड़ दूंगा।

जैसा कि दूसरों ने कहा है, पायथन फ़ंक्शन या विधि मापदंडों पर प्रकार लागू नहीं करता है। यह माना जाता है कि आप जानते हैं कि आप क्या कर रहे हैं, और अगर आपको वास्तव में उस चीज़ के प्रकार को जानने की आवश्यकता है जिसे पारित किया गया था, तो आप इसकी जांच करेंगे और तय करेंगे कि आपके लिए क्या करना है।

ऐसा करने के लिए एक मुख्य उपकरण आइंस्टीन () फ़ंक्शन है।

उदाहरण के लिए, यदि मैं एक विधि लिखता हूं, जो सामान्य utf-8 एन्कोडेड स्ट्रिंग्स के बजाय कच्चे बाइनरी टेक्स्ट डेटा प्राप्त करने की अपेक्षा करता है, तो मैं रास्ते में मापदंडों के प्रकार की जांच कर सकता हूं या तो जो मुझे मिल रहा है, उसके लिए अनुकूल है या एक को बढ़ा सकता है मना करने पर अपवाद

def process(data):
    if not isinstance(data, bytes) and not isinstance(data, bytearray):
        raise TypeError('Invalid type: data must be a byte string or bytearray, not %r' % type(data))
    # Do more stuff

पायथन वस्तुओं में खोदने के लिए सभी प्रकार के उपकरण भी प्रदान करता है। यदि आप बहादुर हैं, तो आप फ़्लाइट पर अपनी मनमानी कक्षाओं की अपनी वस्तुओं को बनाने के लिए भी आयात का उपयोग कर सकते हैं। मैंने JSON डेटा से ऑब्जेक्ट्स को फिर से बनाने के लिए ऐसा किया। इस तरह की बात सी ++ जैसी स्थिर भाषा में एक बुरा सपना होगी।


1

प्रभावी ढंग से टाइपिंग मॉड्यूल का उपयोग करने के लिए (पायथन 3.5 में नया) सभी शामिल हैं ( *)।

from typing import *

और आप उपयोग करने के लिए तैयार होंगे:

List, Tuple, Set, Map - for list, tuple, set and map respectively.
Iterable - useful for generators.
Any - when it could be anything.
Union - when it could be anything within a specified set of types, as opposed to Any.
Optional - when it might be None. Shorthand for Union[T, None].
TypeVar - used with generics.
Callable - used primarily for functions, but could be used for other callables.

हालांकि, अभी भी आप की तरह प्रकार के नाम का उपयोग कर सकते int, list, dict, ...


1

यदि किसी ने परिवर्तनशील प्रकार निर्दिष्ट करना चाहे तो मैंने एक आवरण लागू किया है।

import functools

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for i in range(len(args)):
            v = args[i]
            v_name = list(func.__annotations__.keys())[i]
            v_type = list(func.__annotations__.values())[i]
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        v = result
        v_name = 'return'
        v_type = func.__annotations__['return']
        error_msg = 'Variable `' + str(v_name) + '` should be type ('
        error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
        if not isinstance(v, v_type):
                raise TypeError(error_msg)
        return result

    return check

इसे इस रूप में उपयोग करें:

@type_check
def test(name : str) -> float:
    return 3.0

@type_check
def test2(name : str) -> str:
    return 3.0

>> test('asd')
>> 3.0

>> test(42)
>> TypeError: Variable `name` should be type (<class 'str'>) but instead is type (<class 'int'>)

>> test2('asd')
>> TypeError: Variable `return` should be type (<class 'str'>) but instead is type (<class 'float'>)

संपादित करें

यदि कोई तर्क '(या वापसी) प्रकार घोषित नहीं है, तो उपरोक्त कोड काम नहीं करता है। निम्नलिखित संपादन मदद कर सकता है, दूसरी ओर, यह केवल kwargs के लिए काम करता है और args की जाँच नहीं करता है।

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for name, value in kwargs.items():
            v = value
            v_name = name
            if name not in func.__annotations__:
                continue

            v_type = func.__annotations__[name]

            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ') '
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        if 'return' in func.__annotations__:
            v = result
            v_name = 'return'
            v_type = func.__annotations__['return']
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                    raise TypeError(error_msg)
        return result

    return check
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.