2017-03-11 19 views
6

Tôi có một số mã nguồn được viết cho Python 3.5 mà tôi muốn thực thi theo Python 3.4. Các tính năng duy nhất từ ​​3,5 mà tôi sử dụng mà không có sẵn trong 3,4 là gợi ý loại, vì vậy tôi muốn viết một kịch bản để loại bỏ những hoàn toàn. Điều này có vẻ dễ dàng ngay từ cái nhìn đầu tiên và tôi quyết định viết một số regex để làm điều này, nhưng sau đó tôi nghĩ về một vài trường hợp cạnh và tôi đã không chắc chắn làm thế nào để giải quyết vấn đề cho một chức năng phức tạp hơn như thế này:Xóa gợi ý loại trong nguồn Python theo lập trình

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

Về cơ bản, tôi phải phân tích toàn bộ và xây dựng lại danh sách đối số mà không có chú thích loại. Làm thế nào tôi thậm chí sẽ tiếp cận điều này?

+1

Các [AST mô-đun] (https://docs.python.org/3/library/ast.html) là bạn của bạn trong nhiệm vụ chuyển đổi nguồn, đặc biệt. ['NodeTransformer'] (https://docs.python.org/3/library/ast.html#ast.NodeTransformer). Đối với đảo ngược, bạn có thể cần một số gói bên thứ 3. –

+0

cảm ơn. wow, công cụ đó phức tạp ... Tôi thậm chí sẽ không biết cách nhận ra gợi ý kiểu bằng cách sử dụng ngữ pháp này – Klamann

+1

Hãy xem [ngữ pháp] (https://docs.python.org/3/library/ast.html # abstract-ngữ pháp): ví dụ 'arg' chứa tùy chọn expr 'chú thích' và một' hàmDef' tùy chọn expr 'trả về'. Biến áp của bạn sẽ loại bỏ chúng. –

Trả lời

6

OK, tôi đã nhận nó: D

BUILTIN ast mô-đun

Sử dụng Python để phân tích mã nguồn và sau đó là tuyệt vời astunparse thư viện để tạo ra mã nguồn từ ast phân tích cú pháp một lần nữa. Sau đó, tất cả những gì còn lại là để loại bỏ các chú thích loại:

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

Các thăm TypeHintRemover tất cả các nút trong AST và loại bỏ tất cả các gợi ý kiểu đối số chức năng, các định nghĩa kiểu trả về của mỗi chức năng và tất cả các báo cáo nhập khẩu mà tham khảo mô-đun 'nhập'.

Kết quả là:

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

ý của bạn là gì? – Klamann

+0

bạn nên đọc về [loại gợi ý] (https://www.python.org/dev/peps/pep-0484/) trong Python 3, tôi là một fan hâm mộ lớn của những người. Đầu vào và đầu ra tương đương trong ví dụ này khi nói đến thực thi. Ví dụ: 'bar' được cho là một [' Callable'] (https://docs.python.org/3/library/typing.html#typing.Callable), đó chỉ là gợi ý kiểu, được biểu thị bằng ': ', và lambda ist giá trị mặc định của đối số đó. Gợi ý kiểu là hoàn toàn tùy chọn và sẽ không được đánh giá trong thời gian chạy. – Klamann

+1

sau đó xin vui lòng cho tôi biết chính xác những gì là mất tích, bởi vì từ những gì tôi có thể nhìn thấy, tất cả mọi thứ mà không phải là một gợi ý loại vẫn còn đó. – Klamann

Các vấn đề liên quan