मुझे वैकल्पिक प्रकार संकेत का उपयोग कैसे करना चाहिए?


95

मैं यह समझने की कोशिश कर रहा हूं कि Optionalप्रकार संकेत का उपयोग कैसे करें । से पीईपी-484 , मुझे पता है मैं उपयोग कर सकते हैं Optionalके लिए def test(a: int = None)के रूप में या तोdef test(a: Union[int, None]) या def test(a: Optional[int])

लेकिन निम्नलिखित उदाहरणों के बारे में कैसे?

def test(a : dict = None):
    #print(a) ==> {'a': 1234}
    #or
    #print(a) ==> None

def test(a : list = None):
    #print(a) ==> [1,2,3,4, 'a', 'b']
    #or
    #print(a) ==> None

अगर Optional[type]ऐसा ही लगता है Union[type, None], तो मुझे इसका उपयोग क्यों करना चाहिए Optional[]?

जवाबों:


134

Optional[...]Union[..., None]प्रकार चेकर के लिए एक शॉर्टहैंड नोटेशन है , जो या तो विशिष्ट प्रकार के ऑब्जेक्ट की आवश्यकता है, या None आवश्यक है। किसी भी वैध प्रकार के संकेत... के लिए खड़ा है , जिसमें जटिल यौगिक प्रकार या अधिक प्रकार शामिल हैं। जब भी आपके पास डिफ़ॉल्ट मान के साथ कोई कीवर्ड तर्क हो , तो आपको उपयोग करना चाहिए ।Union[]NoneOptional

तो आपके दो उदाहरणों के लिए, आपके पास dictऔर listकंटेनर प्रकार हैं, लेकिन aकीवर्ड तर्क के लिए डिफ़ॉल्ट मान दिखाता है कि Noneअनुमति बहुत अधिक है Optional[...]:

from typing import Optional

def test(a: Optional[dict] = None) -> None:
    #print(a) ==> {'a': 1234}
    #or
    #print(a) ==> None

def test(a: Optional[list] = None) -> None:
    #print(a) ==> [1, 2, 3, 4, 'a', 'b']
    #or
    #print(a) ==> None

ध्यान दें कि तकनीकी तौर Optional[]पर a का उपयोग करने Union[], या सिर्फ जोड़ने के बीच कोई अंतर नहीं Noneहै Union[]। तो Optional[Union[str, int]]और Union[str, int, None]बिल्कुल यही बात हैं।

व्यक्तिगत रूप से, मैं हमेशाOptional[] ऐसे कीवर्ड तर्क के लिए प्रकार सेट करते समय उपयोग करता हूं, = Noneजो डिफ़ॉल्ट मान सेट करने के लिए उपयोग करता है, इस कारण से Noneबेहतर अनुमति दी जाती है। इसके अलावा, Union[...]एक अलग प्रकार के उर्फ ​​में भाग को स्थानांतरित करना आसान है , या Optional[...]यदि कोई तर्क अनिवार्य हो जाता है, तो बाद में भाग को हटा दें ।

उदाहरण के लिए, आप कहें

from typing import Optional, Union

def api_function(optional_argument: Optional[Union[str, int]] = None) -> None:
    """Frob the fooznar.

    If optional_argument is given, it must be an id of the fooznar subwidget
    to filter on. The id should be a string, or for backwards compatibility,
    an integer is also accepted.

    """

फिर प्रलेखन Union[str, int]को एक प्रकार के उपनाम में खींचकर सुधार किया जाता है:

from typing import Optional, Union

# subwidget ids used to be integers, now they are strings. Support both.
SubWidgetId = Union[str, int]


def api_function(optional_argument: Optional[SubWidgetId] = None) -> None:
    """Frob the fooznar.

    If optional_argument is given, it must be an id of the fooznar subwidget
    to filter on. The id should be a string, or for backwards compatibility,
    an integer is also accepted.

    """

Union[]एक उपनाम में स्थानांतरित करने के लिए परावर्तक को सभी बहुत आसान बना दिया Optional[...]गया क्योंकि इसका उपयोग किया गया था Union[str, int, None]Noneमूल्य यह मूल्य का हिस्सा नहीं है,, सब के बाद एक 'subwidget आईडी' नहीं है Noneध्वज को एक मूल्य के अभाव के लिए है।

साइड नोट: जब तक आपके कोड को केवल Python 3.9 या नए का समर्थन नहीं करना है, आप टाइप लाइब्रेरी में मानक लाइब्रेरी कंटेनर प्रकारों के उपयोग से बचना चाहते हैं, क्योंकि आप कुछ भी नहीं कह सकते हैं कि उन्हें किस प्रकार का होना चाहिए। तो बजाय dictऔर list, उपयोग typing.Dictऔर typing.List, क्रमशः। और जब केवल एक कंटेनर प्रकार से पढ़ते हैं , तो आप बस किसी भी अपरिवर्तनीय सार कंटेनर प्रकार को स्वीकार कर सकते हैं; सूचियाँ और टुपल्स Sequenceऑब्जेक्ट्स हैं, जबकि dictएक Mappingप्रकार है:

from typing import Mapping, Optional, Sequence, Union

def test(a: Optional[Mapping[str, int]] = None) -> None:
    """accepts an optional map with string keys and integer values"""
    # print(a) ==> {'a': 1234}
    # or
    # print(a) ==> None

def test(a: Optional[Sequence[Union[int, str]]] = None) -> None:
    """accepts an optional sequence of integers and strings
    # print(a) ==> [1, 2, 3, 4, 'a', 'b']
    # or
    # print(a) ==> None

Python 3.9 और ऊपर में, मानक कंटेनर प्रकारों को सभी प्रकार के संकेतों में उनका उपयोग करने के लिए अद्यतन किया गया है, PEP 585 देखें । लेकिन , जब आप अब उपयोग कर सकते हैं dict[str, int]या list[Union[int, str]], आप अभी भी अधिक अभिव्यंजक Mappingऔर Sequenceएनोटेशन का उपयोग करना चाह सकते हैं ताकि यह इंगित किया जा सके कि कोई फ़ंक्शन सामग्री को म्यूट नहीं कर रहा है (उन्हें 'केवल पढ़ने के लिए' माना जाता है), और यह कि फ़ंक्शन के साथ काम करेगा कोई भी वस्तु जो क्रमशः मानचित्रण या अनुक्रम के रूप में काम करती है।


@MartijnPieters हम आयात करने की जरूरत नहीं है Dictऔर Listटाइपिंग और लिखने से Optional[Dict]और Optional[List]के बजाय Optional[dict]...
एलिरेज़ा

@Alireza हाँ, और मुझे लगता है कि मेरे जवाब में पहले से ही है। : के लिए देखो की ओर ध्यान दें: के रूप में आप वे क्या प्रकार के शामिल होना चाहिए के बारे में कुछ नहीं कह सकता तुम, प्रकार में मानक पुस्तकालय कंटेनर प्रकार तथापि इशारा का उपयोग कर से बचना चाहते हैं
मार्टिन पीटर्स

सही होने पर मुझे सही करें, लेकिन 3.9 अनुमति देता है listऔर dictटाइप संकेत के लिए उपयोग किया जाता है, (बनाम List, Dict)। python.org/dev/peps/pep-0585
user48956

2
@ user48956: मैंने 3.9 पर एक सेक्शन जोड़ा है।
मार्टिन पीटर्स

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