Pie*_*ult 11 types pattern-matching python-3.10
我正在尝试使用控制台匹配 Python 3.10 中的类型:
t = 12.0
match type(t):
case int:
print("int")
case float:
print("float")
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
File "<stdin>", line 2
SyntaxError: name capture 'int' makes remaining patterns unreachable
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?
mmo*_*eri 11
丢失type()
并在您的类型中添加括号:
t = 12.0
match t:
case int():
print("int")
case float():
print("float")
Run Code Online (Sandbox Code Playgroud)
我不确定为什么你写的不起作用,但这个有效。
Dub*_*low 11
这是新语法的一个常见“问题”:case 子句不是表达式。也就是说,如果将变量名称放入case 子句中,则语法会分配给该名称而不是读取该名称。
match
像switch
其他语言一样思考是一种常见的误解:它不是,甚至不是很接近。switch
case
s 是测试表达式是否相等的表达式switch
;相反,match
case
s 是解包表达式的结构化模式。它实际上更类似于广义的可迭代拆包。它提出这样的问题:“表达式的结构看起来像原因子句的结构吗?”,这是一个与语句所问的问题非常不同的问题。match
match
switch
例如:
t = 12.0
match t:
case newvar: # This is equal to `newvar = t`
print(f"bound a new variable called newvar: {newvar}")
# prints "bound a new variable called newvar: 12.00000000"
# this pattern matches anything at all, so all following cases never run
case 13.0:
print("found 13.0")
case [a, b, c]: # matches an iterable with exactly 3 elements,
# and *assigns* those elements to the variables `a`, `b` and `c`
print(f"found an iterable of length exactly 3.")
print(f"these are the values in the iterable: {a} {b} {c}")
case [*_]:
print("found some sort of iterable, but it's definitely")
print("not of length 3, because that already matched earlier")
case my_fancy_type(): # match statement magic: this is how to type check!
print(f"variable t = {t} is of type {my_fancy_type}")
case _:
print("no match")
Run Code Online (Sandbox Code Playgroud)
所以你的OP实际上做的是这样的:
t = 12.0
tt = type(t) # float obviously
match tt:
case int: # assigns to int! `tt = int`, overwriting the builtin
print(f"the value of int: {int}")
# output: "the value of int: <class 'float'>"
print(int == float) # output: True (!!!!!!!!)
# In order to get the original builtin type, you'd have to do
# something like `from builtins import int as int2`
case float: # assigns to float, in this case the no-op `float = float`
# in fact this clause is identical to the previous clause:
# match anything and bind the match to its new name
print(f"match anything and bind it to name 'float': {float}")
# never prints, because we already matched the first case
case float(): # since this isn't a variable name, no assignment happens.
# under the hood, this equates to an `isinstance` check.
# `float` is not an instance of itself, so this wouldn't match.
print(f"tt: {tt} is an instance of float") # never prints
# of course, this case never executes anyways because the
# first case matches anything, skipping all following cases
Run Code Online (Sandbox Code Playgroud)
坦率地说,我并不完全确定底层实例检查是如何工作的,但它肯定像其他答案所说的那样工作:根据语法的定义match
,类型检查是这样完成的:
match instance:
case type():
print(f"object {instance} is of type {type}!")
Run Code Online (Sandbox Code Playgroud)
所以我们回到我们开始的地方:case 子句不是表达式。正如 PEP 所说,最好将 case 子句视为类似于函数声明,我们在函数声明中命名函数的参数,并可能将一些默认值绑定到这些新命名的参数。但我们永远不会读取case 子句中的现有变量,只会创建新变量。(还涉及一些其他微妙之处,例如,点分访问不能算作此目的的“变量”,但这已经很复杂了,最好在这里结束这个答案。)
首先解释一下问题中的代码:
t = 12.0
match type(t):
case int:
print("int")
case float:
print("float")
Run Code Online (Sandbox Code Playgroud)
在 Python 中,该match
语句通过尝试将主语(的值type(t)
,即float
)纳入其中一种模式来进行操作。
上面的代码有两种模式(case int:
和case float:
)。这些模式,就其语法性质而言,是捕获模式,这意味着它们尝试将主题( 的值type(t)
,即float
)捕获到每个模式中指定的变量名称(分别为名称int
和float
)中。
图案case int:
和case float:
彼此相同。此外,它们都可以匹配任何主题。因此,错误:SyntaxError: name capture 'int' makes remaining patterns unreachable
。
另外,请注意,这两种模式在功能上与 的传统默认模式相同case _:
。 case _:
也只是一个捕获模式,仅此而已。case int:
( 、和case float:
之间的唯一区别case _:
是将捕获主题的变量的名称。)
现在让我们解释一下@mmohaveri 的答案中的代码。
t = 12.0
match t:
case int():
print("int")
case float():
print("float")
Run Code Online (Sandbox Code Playgroud)
上面的match
语句将尝试首先将值放入12.0
模式中case int():
,然后放入模式中case float():
。
这些模式就其语法本质而言是类模式。括号可用于指定模式的位置参数和关键字参数。(括号不是函数调用。)
对于第一个模式 ( case int():
),12.0
不是 的实例int
,因此模式匹配失败。
对于第二个模式, ( case float():
)12.0
是 的实例float
,并且括号内没有指定位置或关键字参数,因此模式匹配成功。
以下是有关匹配过程的更多信息。