一个用于自动升级较新版本语言语法的工具(和 pre-commit 钩子)。
pip install pyupgrade
使用说明请参见 pre-commit
示例 .pre-commit-config.yaml
:
- repo: https://github.com/asottile/pyupgrade rev: v3.17.0 hooks: - id: pyupgrade
-set(()) +set() -set([]) +set() -set((1,)) +{1} -set((1, 2)) +{1, 2} -set([1, 2]) +{1, 2} -set(x for x in y) +{x for x in y} -set([x for x in y]) +{x for x in y}
-dict((a, b) for a, b in y) +{a: b for a, b in y} -dict([(a, b) for a, b in y]) +{a: b for a, b in y}
collections.defaultdict
调用中不必要的 lambda 函数-defaultdict(lambda: []) +defaultdict(list) -defaultdict(lambda: list()) +defaultdict(list) -defaultdict(lambda: {}) +defaultdict(dict) -defaultdict(lambda: dict()) +defaultdict(dict) -defaultdict(lambda: ()) +defaultdict(tuple) -defaultdict(lambda: tuple()) +defaultdict(tuple) -defaultdict(lambda: set()) +defaultdict(set) -defaultdict(lambda: 0) +defaultdict(int) -defaultdict(lambda: 0.0) +defaultdict(float) -defaultdict(lambda: 0j) +defaultdict(complex) -defaultdict(lambda: '') +defaultdict(str)
-'{0} {1}'.format(1, 2) +'{} {}'.format(1, 2) -'{0}' '{1}'.format(1, 2) +'{}' '{}'.format(1, 2)
适用性:
--keep-percent-format
参数。-'%s %s' % (a, b) +'{} {}'.format(a, b) -'%r %2f' % (a, b) +'{!r} {:2f}'.format(a, b) -'%(a)s %(b)s' % {'a': 1, 'b': 2} +'{a} {b}'.format(a=1, b=2)
-u'foo' +'foo' -u"foo" +'foo' -u'''foo''' +'''foo'''
# 只包含无效序列的字符串变为原始字符串 -'\d' +r'\d' # 混合有效和无效序列的字符串会被转义 -'\n\d' +'\n\\d' -u'\d' +r'\d' # 这修复了 python3.3+ 中的语法错误 -'\N' +r'\N'
is
/ is not
比较在 python3.8+ 中,与字面量的比较会产生 SyntaxWarning
,因为这些比较的成功与否取决于具体实现(由于常见对象缓存)。
-x is 5 +x == 5 -x is not 5 +x != 5 -x is 'foo' +x == 'foo'
.encode()
到字节字面量-'foo'.encode() +b'foo' -'foo'.encode('ascii') +b'foo' -'foo'.encode('utf-8') +b'foo' -u'foo'.encode() +b'foo' -'\xa0'.encode('latin1') +b'\xa0'
print(...)
中多余的括号修复 python-modernize/python-modernize#178 问题
# 正确:打印空元组 print(()) # 正确:打印元组 print((1,)) # 正确:括号内的生成器参数 sum((i for i in range(3)), []) # 修复后: -print(("foo")) +print("foo")
isinstance
/ issubclass
/ except
-isinstance(x, (int, int)) +isinstance(x, int) -issubclass(y, (str, str)) +issubclass(y, str) try: raises() -except (Error1, Error1, Error2): +except (Error1, Error2): pass
将 已弃用的 unittest 方法别名 重写为非弃用形式。
from unittest import TestCase class MyTests(TestCase): def test_something(self): - self.failUnlessEqual(1, 1) + self.assertEqual(1, 1) - self.assertEquals(1, 1) + self.assertEqual(1, 1)
super()
调用class C(Base): def f(self): - super(C, self).f() + super().f()
-class C(object): pass +class C: pass -class C(B, object): pass +class C(B): pass
__metaclass__ = type
声明class C: - __metaclass__ = type
str("native")
字面量-str() +'' -str("foo") +"foo"
.encode("utf-8")
-"foo".encode("utf-8") +"foo".encode()
# coding: ...
注释根据 PEP 3120,Python 源代码的默认编码为 UTF-8
-# coding: utf-8 x = 1
__future__
导入可用性:
nested_scopes
、generators
、with_statement
、
absolute_import
、division
、print_function
、unicode_literals
--py37-plus
还会移除 generator_stop
-from __future__ import with_statement
-from io import open -from six.moves import map -from builtins import object # python-future
可用性:
--py36-plus
(及其他)将替换导入一些例子:
-from collections import deque, Mapping +from collections import deque +from collections.abc import Mapping
-from typing import Sequence +from collections.abc import Sequence
-from typing_extensions import Concatenate +from typing import Concatenate
mock
导入可用性:
-from mock import patch +from unittest.mock import patch
yield
=> yield from
def f(): - for x in y: - yield x + yield from y - for a, b in c: - yield (a, b) + yield from c
import sys -if sys.version_info < (3,): # 也理解 `six.PY2`(及其否定)、`six.PY3`(及其否定) - print('py2') -else: - print('py3') +print('py3')
可用性:
--py36-plus
将移除 Python <= 3.5 的代码块--py37-plus
将移除 Python <= 3.6 的代码块# 此示例使用 --py36-plus import sys -if sys.version_info < (3, 6): - print('py3.5') -else: - print('py3.6+') +print('py3.6+') -if sys.version_info <= (3, 5): - print('py3.5') -else: - print('py3.6+') +print('py3.6+') -if sys.version_info >= (3, 6): - print('py3.6+') -else: - print('py3.5') +print('py3.6+')
注意,没有 else
的 if
块不会被重写,因为这可能会引入语法错误。
six
兼容性代码-six.text_type +str -six.binary_type +bytes -six.class_types +(type,) -six.string_types +(str,) -six.integer_types +(int,) -six.unichr +chr -six.iterbytes +iter -six.print_(...) +print(...) -six.exec_(c, g, l) +exec(c, g, l) -six.advance_iterator(it) +next(it) -six.next(it) +next(it) -six.callable(x) +callable(x) -six.moves.range(x) +range(x) -six.moves.xrange(x) +range(x) -from six import text_type -text_type +str -@six.python_2_unicode_compatible class C: def __str__(self): return u'C()' -class C(six.Iterator): pass +class C: pass -class C(six.with_metaclass(M, B)): pass +class C(B, metaclass=M): pass -@six.add_metaclass(M) -class C(B): pass +class C(B, metaclass=M): pass -isinstance(..., six.class_types) +isinstance(..., type) -issubclass(..., six.integer_types) +issubclass(..., int) -isinstance(..., six.string_types) +isinstance(..., str) -six.b('...') +b'...' -six.u('...') +'...' -six.byte2int(bs) +bs[0] -six.indexbytes(bs, i) +bs[i] -six.int2byte(i) +bytes((i,)) -six.iteritems(dct) +dct.items() -six.iterkeys(dct) +dct.keys() -six.itervalues(dct) +dct.values() -next(six.iteritems(dct)) +next(iter(dct.items())) -next(six.iterkeys(dct)) +next(iter(dct.keys())) -next(six.itervalues(dct)) +next(iter(dct.values())) -six.viewitems(dct) +dct.items() -six.viewkeys(dct) +dct.keys() -six.viewvalues(dct) +dct.values() -six.create_unbound_method(fn, cls) +fn -six.get_unbound_function(meth) +meth -six.get_method_function(meth) +meth.__func__ -six.get_method_self(meth) +meth.__self__ -six.get_function_closure(fn) +fn.__closure__ -six.get_function_code(fn) +fn.__code__ -six.get_function_defaults(fn) +fn.__defaults__ -six.get_function_globals(fn) +fn.__globals__ -six.raise_from(exc, exc_from) +raise exc from exc_from -six.reraise(tp, exc, tb) +raise exc.with_traceback(tb) -six.reraise(*sys.exc_info()) +raise -six.assertCountEqual(self, a1, a2) +self.assertCountEqual(a1, a2) -six.assertRaisesRegex(self, e, r, fn) +self.assertRaisesRegex(e, r, fn) -six.assertRegex(self, s, r) +self.assertRegex(s, r) # 注意:仅适用于*字面值* -six.ensure_binary('...') +b'...' -six.ensure_str('...') +'...' -six.ensure_text('...') +'...'
open
别名-with io.open('f.txt') as f: +with open('f.txt') as f: ...
open
模式-open("foo", "U") +open("foo") -open("foo", "Ur") +open("foo") -open("foo", "Ub") +open("foo", "rb") -open("foo", "rUb") +open("foo", "rb") -open("foo", "r") +open("foo") -open("foo", "rt") +open("foo") -open("f", "r", encoding="UTF-8") +open("f", encoding="UTF-8") -open("f", "wt") +open("f", "w")
OSError
别名# 也理解: # - IOError # - WindowsError # - mmap.error 和使用 `from mmap import error` # - select.error 和使用 `from select import error` # - socket.error 和使用 `from socket import error`
def throw():
def catch(): try: throw()
### `TimeoutError` 别名
可用性:
- `--py310-plus` 用于 `socket.timeout`
- `--py311-plus` 用于 `asyncio.TimeoutError`
```diff
def throw(a):
if a:
- raise asyncio.TimeoutError('boom')
+ raise TimeoutError('boom')
else:
- raise socket.timeout('boom')
+ raise TimeoutError('boom')
def catch(a):
try:
throw(a)
- except (asyncio.TimeoutError, socket.timeout):
+ except TimeoutError:
handle_error()
typing.Text
str 别名-def f(x: Text) -> None: +def f(x: str) -> None: ...
-foo, bar, baz = [fn(x) for x in items] +foo, bar, baz = (fn(x) for x in items)
xml.etree.cElementTree
重写为 xml.etree.ElementTree
-import xml.etree.cElementTree as ET +import xml.etree.ElementTree as ET -from xml.etree.cElementTree import XML +from xml.etree.ElementTree import XML
type
-type('') +str -type(b'') +bytes -type(0) +int -type(0.) +float
typing.NamedTuple
/ typing.TypedDict
py36+ 语法可用性:
--py36-plus
。-NT = typing.NamedTuple('NT', [('a', int), ('b', Tuple[str, ...])]) +class NT(typing.NamedTuple): + a: int + b: Tuple[str, ...] -D1 = typing.TypedDict('D1', a=int, b=str) +class D1(typing.TypedDict): + a: int + b: str -D2 = typing.TypedDict('D2', {'a': int, 'b': str}) +class D2(typing.TypedDict): + a: int + b: str
可用性:
--py36-plus
。-'{foo} {bar}'.format(foo=foo, bar=bar) +f'{foo} {bar}' -'{} {}'.format(foo, bar) +f'{foo} {bar}' -'{} {}'.format(foo.bar, baz.womp) +f'{foo.bar} {baz.womp}' -'{} {}'.format(f(), g()) +f'{f()} {g()}' -'{x}'.format(**locals()) +f'{x}'
注意: pyupgrade
有意保守,如果它会使表达式变长或者替换参数过于复杂(因为这可能降低可读性),它就不会创建 f-字符串。
subprocess.run
: 用 text
替换 universal_newlines
可用性:
--py37-plus
。-output = subprocess.run(['foo'], universal_newlines=True) +output = subprocess.run(['foo'], text=True)
subprocess.run
: 用 capture_output=True
替换 stdout=subprocess.PIPE, stderr=subprocess.PIPE
可用性:
--py37-plus
。-output = subprocess.run(['foo'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) +output = subprocess.run(['foo'], capture_output=True)
@functools.lru_cache()
中的括号可用性:
--py38-plus
。import functools -@functools.lru_cache() +@functools.lru_cache def expensive(): ...
可用性:
--py38-plus
。-' '.join(shlex.quote(arg) for arg in cmd) +shlex.join(cmd)
@functools.lru_cache(maxsize=None)
可用性:
--py39-plus
。import functools -@functools.lru_cache(maxsize=None) +@functools.cache def expensive(): ...
可用性:
from __future__ import annotations
--keep-runtime-typing
。--py39-plus
。-def f(x: List[str]) -> None: +def f(x: list[str]) -> None: ...
可用性:
from __future__ import annotations
--keep-runtime-typing
。--py310-plus
。-def f() -> Optional[str]: +def f() -> str | None: ...
-def f() -> Union[int, str]: +def f() -> int | str: ...
可用性:
from __future__ import annotations
--keep-runtime-typing
。--py313-plus
。-def f() -> Generator[int, None, None]: +def f() -> Generator[int]: yield 1
-async def f() -> AsyncGenerator[int, None]: +async def f() -> AsyncGenerator[int]: yield 1
可用性:
from __future__ import annotations
-def f(x: 'queue.Queue[int]') -> C: +def f(x: queue.Queue[int]) -> C:
datetime.UTC
别名可用性:
--py311-plus
。import datetime -datetime.timezone.utc +datetime.UTC
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术 的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高 效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。