2017-03-11 13 views
6

Mam napisany kod źródłowy dla Pythona 3.5, który chcę wykonać w Pythonie 3.4. Jedyną opcją z 3,5, której używam, która nie jest dostępna w wersji 3.4, są wskazówki typu, więc chciałbym napisać skrypt, aby usunąć je całkowicie.Usuwanie podpowiedzi typu programowo w języku Python

Na pierwszy rzut oka wydawało się to łatwe i postanowiłem napisać kilka wyrażeń, aby to zrobić, ale potem pomyślałem o kilku skrajnych przypadkach i nie byłem pewien, jak rozwiązać problem w celu uzyskania bardziej złożonej funkcji, takiej jak ta:

def foo(bar: Dict[T, List[T]], 
     baz: Callable[[T], int] = lambda x: (x+3)/7, 
     **kwargs) -> List[T]: 

Zasadniczo musiałbym przeanalizować całą sprawę i odbudować listę argumentów bez adnotacji typu. Jak miałbym się do tego podejść?

+1

Sieć [moduł AST] (https://docs.python.org/3/library/ast.html) jest twoim przyjacielem w zadaniach transformacji źródło, zwł. ['NodeTransformer'] (https://docs.python.org/3/library/ast.html#ast.NodeTransformer). Na odwrót możesz potrzebować pakietu innej firmy. –

+0

dzięki. Wow, to jest skomplikowane ... Nie wiedziałbym nawet, jak rozpoznać wskazówki do typów za pomocą tej gramatyki. – Klamann

+1

Zobacz [gramatykę] (https://docs.python.org/3/library/ast.html # abstract-gramatyka): na przykład 'arg's zawiera opcjonalne wyrażenie' adnotacja' i 'FunctionDef' opcjonalne wyrażenie' zwraca'. Twój transformator je usunął. –

Odpowiedz

6

OK, rozumiem: D

wbudowanego ast moduł

w Pythonie do analizowania kodu źródłowego, a następnie doskonałe astunparse biblioteka ponownie wygenerować kod źródłowy z przeanalizowanej ast. Wtedy wszystko, co pozostało jest usunięcie adnotacji Typ:

import ast 
import astunparse 

source=""" 
import typing 
from typing import Dict, T, Callable 
from typing import List 

def foo(bar: Dict[T, List[T]], 
     baz: Callable[[T], int] = lambda x: (x+3)/7, 
     **kwargs) -> List[T]: 
    pass 
""" 

class TypeHintRemover(ast.NodeTransformer): 

    def visit_FunctionDef(self, node): 
     # remove the return type defintion 
     node.returns = None 
     # remove all argument annotations 
     if node.args.args: 
      for arg in node.args.args: 
       arg.annotation = None 
     return node 

    def visit_Import(self, node): 
     node.names = [n for n in node.names if n.name != 'typing'] 
     return node if node.names else None 

    def visit_ImportFrom(self, node): 
     return node if node.module != 'typing' else None 

# parse the source code into an AST 
parsed_source = ast.parse(source) 
# remove all type annotations, function return type definitions 
# and import statements from 'typing' 
transformed = TypeHintRemover().visit(parsed_source) 
# convert the AST back to source code 
print(astunparse.unparse(transformed)) 

wizyt TypeHintRemover wszystkich węzłów w AST i usuwa wszelkie podpowiedzi typu w ciągu argumentów funkcji, definicje typu zwrot z każdej funkcji i wszystkie instrukcje importu, które odnoszą się do moduł "pisania".

Wynikiem jest:

def foo(bar, baz=(lambda x: ((x + 3)/7)), **kwargs): 
    pass 
+0

co masz na myśli? – Klamann

+0

powinieneś przeczytać o [typie wskazówek] (https://www.python.org/dev/peps/pep-0484/) w Pythonie 3, jestem ich wielkim fanem. Dane wejściowe i wyjściowe są równoważne w tym przykładzie, jeśli chodzi o wykonanie. Przykład: 'bar' ma być [' Callable'] (https://docs.python.org/3/library/typing.html#typing.Callable), który jest typową podpowiedzią, oznaczoną przez ': ', a lambda jest domyślną wartością tego argumentu. Wskazówka do typu jest całkowicie opcjonalna i nie będzie oceniana w czasie wykonywania. – Klamann

+1

następnie proszę powiedz mi, czego dokładnie brakuje, ponieważ z tego, co widzę, wszystko, co nie jest podpowiedzią typu, nadal tam jest. – Klamann

Powiązane problemy