Рассмотрим следующий код:
class Foo:
def bar(self) -> Foo:
return Foo()
Эта программа фактически завершится сбоем во время выполнения, если вы попытаетесь запустить ее с Python: когда интерпретатор увидит определение bar
, определение Foo
будет еще не закончен. Итак, поскольку Foo
еще не добавлено в глобальное пространство имен, мы пока не можем использовать его в качестве подсказки типа.
Точно так же рассмотрим эту программу:
class Foo:
def bar(self) -> Bar:
return Bar()
class Bar:
def foo(self) -> Foo:
return Foo()
Это взаимозависимое определение страдает от той же проблемы: в то время как мы оцениваем Foo
, Bar
еще не была оценена, поэтому интерпретатор бросает исключение.
Есть три решения этой проблемы. Во-первых, вы можете создать некоторые из ваших строк подсказок типа, эффективно «объявив их вперед»:
class Foo:
def bar(self) -> "Foo":
return Foo()
Это удовлетворяет интерпретатору Python и не нарушает сторонние инструменты, такие как mypy: они могут просто удалить кавычки перед разбором типа. Основным недостатком является то, что этот синтаксис выглядит некрасиво и неуклюже.
Второе решение заключается в использовании синтаксиса комментариев типа:
class Foo:
def bar(self):
# type: () -> Foo
return Foo()
Это имеет те же преимущества и недостатки, что и первое решение: оно удовлетворяет интерпретатору и инструментам, но выглядит хакерским и уродливым. Он также имеет дополнительное преимущество, заключающееся в том, что он поддерживает ваш код обратно совместимым с Python 2.7.
Третье решение - только Python 3.7+ - используйте директиву from __future__ import annotations
:
from __future__ import annotations
class Foo:
def bar(self) -> Foo:
return Foo()
Это автоматически сделает все аннотации представленными в виде строк. Таким образом, мы получаем преимущество первого решения, но без уродства.
Это поведение в конечном итоге станет стандартным в будущих версиях Python.
Также оказывается, что автоматическое создание всех строк аннотаций может привести к некоторым улучшениям производительности. Создание типов, таких как List[Dict[str, int]]
, может быть удивительно дорогим: они просто регулярные выражения во время выполнения и оцениваются так, как если бы они были написаны как List.__getitem__(Dict.__getitem__((str, int))
.
Оценить это выражение довольно дорого: в итоге мы выполняем два вызова метода, создаем кортеж и создаем два объекта. Конечно, это не считая дополнительной работы, которая происходит в самих методах __getitem__
- и работа, которая происходит в этих методах, оказывается нетривиальной из-за необходимости.
(Короче говоря, им нужно создавать специальные объекты, которые гарантируют, что типы, подобные List[int]
, не могут быть использованы ненадлежащим образом во время выполнения - например, в isinstance
проверках и т. П.)
Вот пара - никакая идея, как хорошо они работают, к сожалению...
(Бесплатный) http://www.wangz.net/gsqlparser/sqlpp/sqlformat.htm
http://www.sqlinform.com/ (свободный для персонального использования)
Попробуйте redgate SQLPrompt. Это имеет 14-дневную пробную версию.
Красный Логический элемент "SQL Осуществляет рефакторинг" Очень хороший. Мы купили его
Или
Свободный пакет инструментов SSMS, но мы не используем функции расположения
Выезд Sql помогает:
Это имеет некоторую функцию формата.
http://www.roundpolygons.com/Default.aspx?PageContentID=5&tabid=92
Я предложил бы загрузить пробную версию, чтобы видеть, соответствует ли она Вашей потребности.
Попробуйте www.softfrontiers.com/Downloads/ReIndenter.shtml Бесплатно (или пожертвуйте) и загрузите.
Работает с кодом C # и SQL Server.
Работает очень быстро и не меняет код, за исключением отступов и комментариев в конце, где они отсутствуют и возможны.