Python 3.12新功能(2)- 类型参数语法

为了更好地支持泛型(Generics), Python 3.12中为声明泛型中的类型参数提供了更加便利的语法形式。作为对比,让我们先看看Python 3.11中是如何声明泛型参数类型的。

# demo——3.11.py - demonstrate type variables in generics
# CopyLeft by "Bruce Jia" if it works; Otherwise I don't know who wrote it, :)
#

import sys
print(sys.version) # just showing which version we're using


from typing import TypeVar
from collections.abc import Sequence


T = TypeVar("T")

def min(l: Sequence[T]) -> T:
	# ignore the logic ...
	return l[0]


def max(l: Sequence[T]) -> T:
	# ignore the logic ...
	return l[1]


print(min([1,2]))
print(max([1,2]))

这上面的代码实现了两个泛型函数min和max,因为仅仅是为了展示语言特性没有真正实现逻辑。代码能够在Python 3.11和3.12中运行。注意类型T被定义为一个typing.TypeVar,这样Python的解释器看到min和max的函数签名时就不会发懵了。如果不先定义T,那么就会出现下面的错误。

这样每次都需要一条语句来定义类型T,也很繁琐。所以Python 3.12中进行了改进,可以写得更加简洁。

# demo_3_12.py - demonstrate type variables in generics
# CopyLeft by "Bruce Jia" if it works; Otherwise I don't know who wrote it, :)
#

import sys
print(sys.version) # just showing which version we're using


from collections.abc import Sequence


def min[T](l: Sequence[T]) -> T:
	# ignore the logic ...
	return l[0]


def max[T](l: Sequence[T]) -> T:
	# ignore the logic ...
	return l[1]


print(min([1,2]))
print(max([1,2]))

上面代码中在函数名min/max的后边声明类型T,放入方括号中就可以了。Python解释器做语法分析的时候就知道T是一个类型定义了。

有一点需要注意的是,如果将T定义为typing.TypeVar("T") 之后,T在当前的范围内是有明确定义的,所以后边的函数或者类使用T的时候都是没有问题的。但是如果是通过Python 3.12的语法声明了T, 那么这时候T的有效范围仅仅是声明它的函数或者类定义中有效。例如


def avg(l: Sequence[T]) -> T:
	# ...
	return l[2]


print(avg([1, 3, 2, 2]))

如果将这段代码放在demo_3.11.py的尾部,是可以运行的;但是放在demo_3.12.py末尾,Python会报错,因为T没有被定义。

【上面文字中有点地方会出现声明和定义两个词,这里的目的是想借用C/C++中的概念。对于Python中的类型,使用“显式定义”和“隐式定义”或许更好,因为根本不存在什么声明的概念。哪位同学有更好的方法将这个讲清楚,欢迎交流指导。】

跟类型参数定义紧密相关的还有一个新东西,就是可以使用type语句来定义一个类型。例如,

# demo_typealias.py
# CopyLeft by "Bruce Jia" if it works; Otherwise I don't know who wrote it, :)
#

type Point = tuple[float, float]

class Rectangle:
	def __init__(self, min: Point, max: Point):
		self._min = min
		self._max = max

	def area(self) -> float:
		# ignore ...
		return 0


def calc_distance(p1: Point, p2: Point) -> float:
	# ignore the implementation ...
	return 3.14159

类似于C++中的typedef,这里通过type语句定义了类型Point, 它实际上是一个包含两个float元素的元组。定义了Point之后,我们可以使用它定义其他的类或者函数。那么这里的Point的类型,到底是什么呢?我们可以问问解释器。

print(type(Point))

Python会告诉我们,它是 <class 'typing.TypeAliasType'>。嗯,对,它就是一个类型别名

(限于时间,今天就短-更到这里了。后面继续加油~~,大家一起努力学习,用Python写出更加优雅的代码~)

各位小伙伴如果对于类型参数的语法感兴趣,也可以追本溯源看看PEP 695。PEP 695 – Type Parameter Syntax | peps.python.org

  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bruce Jia(上海)

熬夜码字换酒钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值