如何将大小写与类类型一起使用
我想使用 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)
输出如下:
aaa
bbb
???
???
I want to use match
to determine an action to perform based on a class type
. I cannot seem to figure out how to do it. I know their are other ways of achieving this, I would just like to know can it be done this way. I am not looking for workarounds of which there are many.
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)
The output is as follows:
aaa
bbb
???
???
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您想要匹配一个常量值。这是常量值模式的情况:
常量值模式必须是形式
NAME ('.' NAME)+
- 即名称后跟至少一个属性查找。裸名称将被视为捕获模式。这对于其他模块中定义的类来说很好,但是如果您想与同一模块中的类匹配,您可以导入当前模块:或者如果您想避免循环导入,您可以创建一个命名空间:
请注意,如果您选择在“导入当前模块”路径中,您需要注意 Python 的奇怪之处,即入口点脚本被视为
__main__
模块,无论其文件名如何。如果您执行python somefile.py
并尝试在其中导入somefile
,它将执行第二次运行
somefile.py< /code> 作为
somefile
模块并创建所有类的第二个副本,并且您的 match 语句将不起作用。You want to match against a constant value. That's a case for constant value patterns:
Constant value patterns must be of the form
NAME ('.' NAME)+
- that is, a name followed by at least one attribute lookup. A bare name will be considered a capture pattern. That's fine for classes defined in other modules, but if you want to match against classes in the same module, you can import the current module:or if you want to avoid the circular import, you can create a namespace:
Note that if you go the "import the current module" route, you need to be aware of Python's weird thing where the entry point script is considered the
__main__
module, regardless of its file name. If you dopython somefile.py
and try toimport somefile
inside that, it will perform a second run ofsomefile.py
as thesomefile
module and create a second copy of all your classes, and your match statements won't work.尝试在
match
行中使用typ()
而不是typ
:输出:
更新:
基于 OP 的评论询问对于比问题中的示例类更普遍地适用于类的解决方案,这里有一个解决此问题的答案:
输出:
更新#2:
基于 这篇 文章以及对 PEP 364 此处,我创建了一个示例,展示了一些数据类型(Python
match
可以使用内置类、集合模块中的类和用户定义的类来根据类类型(或更一般地说,数据类型)确定要执行的操作:输出:
正如另一篇文章中的这个答案所述:
换句话说,如果我们尝试说
case aaa:
,aaa
将被解释为我们分配主题的名称 (typ 在您的代码中)并且将始终匹配并阻止任何匹配后续
case
行的尝试。为了解决这个问题,对于可以使用点指定的类类型名称(或通常的名称)(可能因为它们属于命名空间或另一个类),我们可以使用点名称作为不会被解释为名称捕获。
对于内置类型
str
,我们可以使用case __builtins__.str:
。对于Python的collections
模块中的Counter
类,我们可以使用case collections.Counter:
。如果我们在另一个名为namespacing_class
的类中定义类aaa
,我们可以使用case namepacing_class.aaa:
。但是,如果我们在 Python 代码的顶层定义类
bbb
,我不清楚是否有任何方法可以使用点名称来引用它,从而避免名称捕获。可能有一种方法可以在
case
行中指定用户定义的类type
,但我还没有弄清楚。否则,对于可点类型而不是非可点类型执行此操作似乎相当任意(并且不幸)。Try using
typ()
instead oftyp
in thematch
line:Output:
UPDATE:
Based on OP's comment asking for solution that works for classes more generally than the example classes in the question, here is an answer addressing this:
Output:
UPDATE #2:
Based on this post and some perusal of PEP 364 here, I have created an example showing how a few data types (a Python builtin, a class from the collections module, and a user defined class) can be used by
match
to determine an action to perform based on a class type (or more generally, a data type):Outputs:
As stated in this answer in another post:
In other words, if we try to say
case aaa:
for example,aaa
will be interpreted as a name to which we assign the subject (typ
in your code) and will always match and block any attempts to match subsequentcase
lines.To get around this, for class type names (or names generally) that can be specified using a dot (perhaps because they belong to a namespace or another class), we can use the dotted name as a pattern that will not be interpreted as a name capture.
For built-in type
str
, we can usecase __builtins__.str:
. For theCounter
class in Python'scollections
module, we can usecase collections.Counter:
. If we define classaaa
within another class namednamespacing_class
, we can usecase namespacing_class.aaa:
.However, if we define class
bbb
at the top level within our Python code, it's not clear to me that there is any way to use a dotted name to refer to it and thereby avoid name capture.It's possible there's a way to specify a user defined class
type
in acase
line and I simply haven't figured it out yet. Otherwise, it seems rather arbitrary (and unfortunate) to be able to do this for dottable types and not for non-dottable ones.在相关情况下使用
if
防护怎么样?参考:请参阅 PEP 的向模式添加条件部分636.
How about using an
if
guard in the relevant cases?Reference: See the Adding conditions to patterns section of PEP 636.