2017-03-11 6 views
6

私は、Python 3.5用のソースコードをPython 3.4で実行可能にしたいと思っています。私が使用している3.4の3.5の唯一の機能はタイプヒントなので、それらを完全に削除するスクリプトを書いてみたいと思います。Pythonソースのタイプヒントをプログラムで削除する

これは最初の一見では十分に簡単に思えましたが、これを行うためにいくつかの正規表現を書くことにしましたが、いくつかのエッジケースについて考えましたが、次のような、

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

基本的には、すべてを解析し、型名なしで引数リストを再構築する必要があります。どのように私はこれに近づくだろうか? Dソースコードを解析する

使用Pythonの組み込みastモジュールをして、優れたastunparseライブラリが再び解析され、ASTからソースコードを生成する:

+1

[ASTモジュール](https://docs.python.org/3/library/ast.html)はESP、ソースの変換作業であなたの友達です。 ['NodeTransformer'](https://docs.python.org/3/library/ast.html#ast.NodeTransformer)。逆の場合は、サードパーティ製のパッケージが必要な場合があります。ありがとうございます。 –

+0

うわー、そのものは複雑です...私はこの文法を使ってタイプヒントを認識する方法も知らないでしょう – Klamann

+1

[grammar](https://docs.python.org/3/library/ast.html)を見てください。 #抽象文法):例えば、 'arg'はオプションのexpr' annotation'と 'FunctionDef'オプションのexpr' returns'を含みます。変圧器はそれらを除去するでしょう。 –

答えて

6

OK、私はそれを得ました。その後、残っているすべてのタイプの注釈を削除することです:

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)) 

TypeHintRemover訪問AST内のすべてのノードと関数の引数、各関数の戻り値の型の定義とを参照するすべてのimportステートメント内のすべてのタイプのヒントを削除します'入力'モジュール。

結果は次のとおりです。

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

どういう意味ですか? – Klamann

+0

Python 3で[type hints](https://www.python.org/dev/peps/pep-0484/)を読んでください。私はそれらの大ファンです。この例では、入力と出力は実行時に等価です。例: 'bar'は' [Callable'](https://docs.python.org/3/library/typing.html#typing.Callable)であると考えられます。これは型ヒントであり、 ': 'であり、ラムダはその引数のデフォルト値です。型ヒントは完全にオプションであり、実行時には評価されません。 – Klamann

+1

私は見ることができるので、タイプヒントではないものはすべてそこにあるので、正確に何が欠けているか教えてください。 – Klamann

関連する問題