pau*_*are 10 python types class case match
我想用来match确定基于类执行的操作type。我似乎不知道该怎么做。我知道他们还有其他方法可以实现这一目标,我只是想知道是否可以通过这种方式完成。我并不是在寻找有很多的解决方法。
class aaa():
pass
class bbb():
pass
def f1(typ):
if typ is aaa:
print("aaa")
elif typ is bbb:
print("bbb")
else:
print("???")
def f2(typ):
match typ:
case aaa():
print("aaa")
case bbb():
print("bbb")
case _:
print("???")
f1(aaa)
f1(bbb)
f2(aaa)
f2(bbb)
Run Code Online (Sandbox Code Playgroud)
输出如下:
aaa
bbb
???
???
Run Code Online (Sandbox Code Playgroud)
尝试使用typ()而不是typ在行中match:
class aaa():
pass
class bbb():
pass
def f1(typ):
if typ is aaa:
print("aaa")
elif typ is bbb:
print("bbb")
else:
print("???")
def f2(typ):
match typ():
case aaa():
print("aaa")
case bbb():
print("bbb")
case _:
print("???")
f1(aaa)
f1(bbb)
f2(aaa)
f2(bbb)
Run Code Online (Sandbox Code Playgroud)
输出:
aaa
bbb
aaa
bbb
Run Code Online (Sandbox Code Playgroud)
更新:
根据OP的评论,要求提供比问题中的示例类更普遍的类解决方案,以下是解决此问题的答案:
aaa
bbb
aaa
bbb
Run Code Online (Sandbox Code Playgroud)
输出:
aaa
bbb
aaa
bbb
Run Code Online (Sandbox Code Playgroud)
更新#2:
基于这篇文章和对matchPEP 364 的一些阅读,我创建了一个示例,展示了如何使用一些数据类型(Python 内置、集合模块中的类和用户定义的类)根据类类型(或更一般地说,数据类型)确定要执行的操作:
class aaa():
pass
class bbb():
pass
def f1(typ):
if typ is aaa:
print("aaa")
elif typ is bbb:
print("bbb")
else:
print("???")
def f2(typ):
match typ.__qualname__:
case aaa.__qualname__:
print("aaa")
case bbb.__qualname__:
print("bbb")
case _:
print("???")
f1(aaa)
f1(bbb)
f2(aaa)
f2(bbb)
Run Code Online (Sandbox Code Playgroud)
输出:
aaa
str
Counter
Run Code Online (Sandbox Code Playgroud)
正如另一篇文章中的回答所述:
case 子句中的变量名称被视为名称捕获模式。它始终匹配并尝试对变量名称进行赋值。...我们需要将名称捕获模式替换为非捕获模式,例如使用. 用于属性查找的运算符。点是匹配非捕获模式的关键。
换句话说,如果我们尝试说,case aaa:例如,aaa将被解释为我们分配主题的名称(typ在您的代码中),并且将始终匹配并阻止任何匹配后续case行的尝试。
为了解决这个问题,对于可以使用点指定的类类型名称(或通常的名称)(可能因为它们属于命名空间或另一个类),我们可以使用点名称作为不会被解释为名称捕获。
对于内置类型str,我们可以使用case __builtins__.str:. 对于CounterPythoncollections模块中的类,我们可以使用case collections.Counter:. 如果我们aaa在另一个名为 的类中定义类namespacing_class,我们可以使用case namespacing_class.aaa:.
但是,如果我们bbb在 Python 代码中的顶层定义类,我不清楚是否有任何方法可以使用点名称来引用它,从而避免名称捕获。
可能有一种方法可以type在一行中指定用户定义的类case,但我还没有弄清楚。否则,能够对可点类型而不是非可点类型执行此操作似乎相当任意(并且不幸)。
您想要匹配一个常量值。这是恒定值模式的情况:
match typ:
case somemodule.ClassOne:
...
case anothermodule.ClassTwo:
...
Run Code Online (Sandbox Code Playgroud)
常量值模式必须采用以下形式NAME ('.' NAME)+:即名称后跟至少一个属性查找。裸名称将被视为捕获模式。这对于其他模块中定义的类来说很好,但是如果您想与同一模块中的类匹配,您可以导入当前模块:
# in somemodule.py
import somemodule
class ClassOne:
...
class ClassTwo:
...
match typ:
case somemodule.ClassOne:
...
case somemodule.ClassTwo:
...
Run Code Online (Sandbox Code Playgroud)
或者如果你想避免循环导入,你可以创建一个命名空间:
import types
options = types.SimpleNamespace()
options.ClassOne = ClassOne
options.ClassTwo = ClassTwo
match typ:
case options.ClassOne:
...
case options.ClassTwo:
...
Run Code Online (Sandbox Code Playgroud)
请注意,如果您选择“导入当前模块”路线,则需要注意 Python 的奇怪之处,即入口点脚本被视为模块__main__,而不管其文件名如何。如果您这样做python somefile.py并尝试import somefile进入其中,它将作为模块执行第二次运行并创建所有类的第二个副本,并且您的匹配语句将不起作用。somefile.pysomefile