Podczas próby napisania małego, zaciemnionego sprawdzania typu, wykryto niedopuszczalny wzorzec kodu. Jednak niekonsekwentnie nie działa poprawnie. Jest to kod, który został napisany w trybie init, aby go przetestować.TypeError: argument function() po * musi być sekwencją, a nie generatorem
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)
Poniżej przedstawiono konwersację z interpreterem języka Python i podświetlany błąd. Wygenerowano kod TypeError
, ale nie ten, który był oczekiwany. Chociaż generatory były w porządku, teraz zawodzą.
>>> 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
Funkcja statictypes
mogą być zapisane, a funkcja isallinstance
nowo i owijania. Najprostszym rozwiązaniem jest przepisanie generatu w statictypes
, aby było zrozumieniem listy.
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)])))
Następnie, isallinstance
będzie rozpoczęciem pracy zgodnie z oczekiwaniami, gdy jest on ponownie od początku. TypeError
stwierdzające, co było nie tak z drugim argumentem, zostało poprawnie wygenerowane zgodnie z oczekiwaniami.
>>> 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'>
Pytania:
- Dlaczego pierwsza funkcja z generatorem somtimes pracy, a innym razem nie?
- Dlaczego generator nie jest uważany za sekwencję (ponieważ generuje sekwencję)?
- Dlaczego sekwencja jest potrzebna, gdy generator działa przez jakiś czas?
Ad 1 .: Spójrz na linię, w której wystąpił błąd - nie ma wywołania 'isinstance()' w tej linii. –
OK, widzę - błąd jest zgłaszany w niewłaściwym wierszu, z powodu błędu wymienionego w 3. –
Pracuję z Pythonem przez około 6 lat i nie potrzebuję sprawdzania typu. To był tylko eksperyment, aby zobaczyć, jak mały może być funkcjonalny sprawdzian typu. Prawie nikt nie wydaje się korzystać z adnotacji funkcji, a to wydawało się twórczym sposobem na ich wykorzystanie. –