2012-07-27 11 views
6

एक छोटे, obfuscated प्रकार चेकर लिखने की कोशिश करते समय, एक अस्वीकार्य कोड पैटर्न खोजा गया था। हालांकि, यह असंगत रूप से ठीक से काम करने में विफल रहता है। यह वह कोड है जिसे अनियमित रूप से इसके साथ परीक्षण करने के लिए लिखा गया था।TypeError: फ़ंक्शन() तर्क * अनुक्रम होना चाहिए, जनरेटर नहीं

def statictypes(a): 
    def b(a, b, c): 
     if b in a and not isinstance(c, a[b]): raise TypeError('{} should be {}, not {}'.format(b, a[b], type(c))) 
     return c 
    return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*(b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c))))) 

@statictypes 
def isallinstance(iterable: object, class_or_type_or_tuple: (type, tuple)) -> bool: 
    """isallinstance(iterable, class_or_type_or_tuple) -> bool 

    Return whether all items in an iterable are instances of a class or of a 
    subclass thereof. With a type as second argument, return whether that is 
    all items' type. The form using a tuple, isallinstance(x, (A, B, ...)), 
    is a shortcut for any(isallinstance(x, y) for y in (A, B, ...)). 
    """ 
    return all(isinstance(item, class_or_type_or_tuple) for item in iterable) 

निम्नलिखित पाइथन के दुभाषिया के साथ बातचीत दिखाता है और आने वाली त्रुटि को हाइलाइट करता है। एक TypeError उत्पन्न होता है, लेकिन अपेक्षित नहीं था। जबकि जेनरेटर ठीक थे, अब वे असफल हो गए।

>>> isallinstance(range(1000000), int) 
True 
>>> isallinstance(range(1000000), (int, float)) 
True 
>>> isallinstance(range(1000000), [int, float]) 
Traceback (most recent call last): 
    File "<pyshell#26>", line 1, in <module> 
    isallinstance(range(1000000), [int, float]) 
    File "C:\Users\schappell\Downloads\test.py", line 5, in <lambda> 
    return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*(b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c))))) 
TypeError: isallinstance() argument after * must be a sequence, not generator 

statictypes समारोह में लिखा जा सकता है, और isallinstance समारोह नए सिरे से परिभाषित और लपेटा। सबसे आसान समाधान सूची समझने के लिए statictypes में जेनरेटियर को फिर से लिखना है।

def statictypes(a): 
    def b(a, b, c): 
     if b in a and not isinstance(c, a[b]): raise TypeError('{} should be {}, not {}'.format(b, a[b], type(c))) 
     return c 
    return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*[b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c)]))) 

उसके बाद, isallinstance काम करने शुरू कर एक बार यह खरोंच से निर्मित किया गया है के रूप में उम्मीद करेंगे। TypeError बताते हुए कि दूसरे तर्क के साथ क्या गलत था वांछित के रूप में ठीक से उत्पन्न किया गया है।

>>> isallinstance(range(1000000), int) 
True 
>>> isallinstance(range(1000000), (int, float)) 
True 
>>> isallinstance(range(1000000), [int, float]) 
Traceback (most recent call last): 
    File "<pyshell#29>", line 1, in <module> 
    isallinstance(range(1000000), [int, float]) 
    File "C:\Users\schappell\Downloads\test.py", line 5, in <lambda> 
    return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*[b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c)]))) 
    File "C:\Users\schappell\Downloads\test.py", line 5, in <listcomp> 
    return __import__('functools').wraps(a)(lambda *c: b(a.__annotations__, 'return', a(*[b(a.__annotations__, *d) for d in zip(a.__code__.co_varnames, c)]))) 
    File "C:\Users\schappell\Downloads\test.py", line 3, in b 
    if b in a and not isinstance(c, a[b]): raise TypeError('{} should be {}, not {}'.format(b, a[b], type(c))) 
TypeError: class_or_type_or_tuple should be (<class 'type'>, <class 'tuple'>), not <class 'list'> 

सवाल:

  1. जनरेटर के साथ पहली बार समारोह somtimes है क्यों काम करते हैं और दूसरी बार असफल?
  2. जनरेटर को अनुक्रम क्यों नहीं माना जाता है (क्योंकि यह अनुक्रम उत्पन्न करता है)?
  3. एक जनरेटर स्पष्ट रूप से कुछ समय काम करता है जब अनुक्रम की आवश्यकता क्यों होती है?

उत्तर

8
  1. क्योंकि isinstance, अन्य मदहोश मानक पुस्तकालय कार्यों के एक जोड़े की तरह, एक अलग बात है जब आप इसे अन्य दृश्यों की तुलना में एक टपल देता है। अर्थात्, यह काम करता है, और जांचता है कि प्रकार दिया गया है।
  2. क्योंकि यह नहीं है। sequence protocol definition देखें। इसे एक होने के लिए __getitem__ को लागू करने की आवश्यकता होगी।
  3. एक बग, जो अभी भी hasn't been merged है, जो आपको बता रहा है कि आपका जनरेटर टूटा हुआ है, लेकिन गलत त्रुटि संदेश के साथ।

इसके अलावा, कृपया किसी भी चीज़ के लिए इस तरह की जांच के प्रकार के साथ हमारी सुंदर भाषा को गंदे न करें लेकिन अच्छे कारणों से :)।

+0

विज्ञापन 1: उस रेखा में त्रुटि को देखते हुए - उस पंक्ति में कोई 'isinstance()' कॉल नहीं है। –

+2

ठीक है, मैं देखता हूं - गलत स्थिति में त्रुटि रिपोर्ट की गई है, 3. –

+0

में वर्णित बग के कारण मैं लगभग 6 वर्षों तक पाइथन के साथ काम कर रहा हूं और टाइपिंग की आवश्यकता नहीं है। यह देखने के लिए सिर्फ एक प्रयोग था कि एक कार्यात्मक प्रकार-परीक्षक कितना छोटा बनाया जा सकता था। शायद ही कोई फंक्शन एनोटेशन का लाभ उठा रहा है, और यह उनका उपयोग करने के लिए एक रचनात्मक तरीका प्रतीत होता है। –

संबंधित मुद्दे