编程与软件工程hillelwayne.com
Python 模式匹配的几宗罪
Crimes with Python's pattern matching
2022 — 2025,它一次次回到首页
黑点是上首页(≥ 50 分)的那次投稿,空心点是没冲上去的投稿,点越大分数越高。
导读
这篇文章讨论 Python 的结构化模式匹配(match/case)在与 ABC、__instancecheck__ 等对象模型钩子结合时,能做出哪些反直觉甚至“离谱”的行为。作者借这些例子审视 Python 的语义设计,尤其是类、类型与实例检查之间的关系。
为什么经久不衰:它把模式匹配和 ABC 背后的隐蔽机制摊开,提醒读者语言特性组合会带来意外语义;今天读仍能加深对 Python 对象模型和设计取舍的理解。
HN 评论精选
指出文章示例可绕过 ABC 缓存直接实现 __instancecheck__,质疑作者是否漏掉了这一点。
看看 Python 版 ABC 的实现就会发现,__subclasshook__ 并没有什么语言魔法,它只是把方法注册到 __instancecheck__ 中调用。所以如果直接实现 __instancecheck__,能得到同样行为,但没有外面的缓存。……我是不是漏掉了文章的某个要点,还是作者忽略了这一点?
w-m查看英文原文
Looking in the implementation of the Python version of ABC[0], you'll see that `__subclasshook__` doesn't do any language magic, it just registers the method to be called in `__instancecheck__`. So if you just implement `__instancecheck__` directly, you get the same behavior, but without the caching around it. class OneWayMeta(type): seen_classes = set() @classmethod def __instancecheck__(cls, instance): C = instance.__class__ print(f"trying {C}") if C in cls.seen_classes: return False cls.seen_classes |= {C} return True class OneWay(metaclass=OneWayMeta): pass def f(x): match x: case OneWay(): print(f" {x} is a new class") case _: print(f"we've seen {x}'s class before") if __name__ == "__main__": f("abc") f([1, 2, 3]) f("efg") When running: trying <class 'str'> abc is a new class trying <class 'list'> [1, 2, 3] is a new class trying <class 'str'> we've seen efg's class before Am I missing a particular point the article is making, or did the author overlook this? [0]: https://github.com/python/cpython/blob/main/Lib/_py_abc.py
批评 Python 的“简单性”取舍放错重点,反而造成语义上的复杂。
读这篇文章让我忍不住觉得,Python 把“简单”放在了无关紧要的地方。比如没有把模式匹配做成表达式、没有多表达式 lambda,理由都是简单;但我没见过这些特性在其他语言里造成问题。真正重要的应该是语义上的简单,可 Python 里的简单性论证常常被用来强加任意的语法和语义复杂性。
noelwelsh查看英文原文
Reading this I can't help feeling that Python puts the "simplicity" in all the places that don't matter. Simplicity is the reason given for not having useful language features like pattern matches as expressions, or lambdas with multiple expressions, but I've never seen these features[1] cause problems in other languages. And then we have this... Surely semantic simplicity is the simplicity that actually matters, but the way the simplicity argument is used in Python is often to enforce arbitrary syntactic and semantic complexity. [1] It's almost ridiculous to call these features as they're just a consequence of the underlying language model. E.g. if you have expression blocks you have lambdas with multiple expressions with no extra work.
读者没看懂作者为何对示例输出感到震惊,质疑其中到底有什么问题。
作者引用输出说“但 Python 当然会限制这种把戏吧?…… 哦。哦我的。”我肯定有点迟钝、漏掉了明显的东西,但作者在这里到底在回应什么?这有什么错或不好?
nadavr查看英文原文
> But surely Python clamps down on this chicanery, right? > > $ py10 abc.py > 10 is not iterable > string is iterable > [1, 2, 3] is iterable > > Oh. > > Oh my. I'm sure I'm being dense and missing the obvious but ... what is the author responding to here? What's wrong or bad?
批评 Python 把类当类型、ABC 不等同接口,认为接口/协议与实现解耦才更合理。
不该用这个的真正原因是,Python 对类型和类的理解是错的。在 OOP 中类不是类型,接口才是;ABC 是这一点很差的复制品。Guido 显然没读相关文献,在 PEP-3119 里说 ABC 与接口并非本质不兼容,但有很大重叠,先让接口支持者解释为什么接口更好。让我试试:接口更好,因为对象的协议不绑定于其实现;在良好封装下,接口表示关于一个类作为类型可用的信息。子类可能只是复用实现却不遵守同一协议,或者两个可互换的类根本没有继承关系。Python 在很多方面不错,但许多设计似乎有意无视编程语言先前的研究;TypeScript 处理得好得多。
rileyphone查看英文原文
The real reason why you shouldn't use this is that Python is wrong about typing and classes. In OOP, classes are not types; interfaces are [0]. ABCs are a poor replica of this. Guido, having clearly avoided any relevant literature, states, in PEP-3119 [1]: > ABCs are not intrinsically incompatible with Interfaces, but there is considerable overlap. For now, I’ll leave it to proponents of Interfaces to explain why Interfaces are better. Let me try: interfaces are better because the protocol of an object isn't tied to its implementation, but in a properly encapsulated world an interface represents the information available about a class as a type [2]. A subclass may just be reusing an implementation without adhering to the same protocol, or two interchangeable classes might have no inheritance relationship. Python is in a lot of ways a nice language, and I've certainly enjoyed programming in it, but many points of its design seem intentionally unobservant of prior work and research in programming languages, though perhaps it's equally an indictment of that research that the most popular languages ignore it so much. Typescript handles this much better, though neither it or Java eschew using classes as types entirely. [0] https://dl.acm.org/doi/10.1145/96709.96721 [1] https://peps.python.org/pep-3119/#abcs-vs-interfaces [2] https://dl.acm.org/doi/10.1145/2509578.2514738
历次讨论
同类还值得读
开源应用架构
The Architecture of Open Source Applications
《开源软件架构》(AOSA)是一本在线免费书,邀请知名开源项目的作者亲自剖析其内部设计,涵盖 SQLAlchemy、LLVM、Audacity、Apache、Bash 等系统。
编程与软件工程上首页 9 次 · 2011–2024aosabook.org编辑精选编程语言简史:简短、不完整且多半错误
A Brief, Incomplete, and Mostly Wrong History of Programming Languages
一篇以戏谑、故意不准确的方式回顾编程语言史的博客文章,用夸张轶事和讽刺定义串起 Lisp、C、C++、Java、JavaScript、PHP 等语言。
编程与软件工程上首页 8 次 · 2009–2021james-iry.blogspot.comSQLite 是如何测试的
How SQLite is tested
SQLite 官方文档页,系统介绍 SQLite 的测试体系:多种测试方法(TCL 测试、模糊测试、回归测试、静态分析等)和海量测试用例,展示了这个小型开源项目如何靠极致测试获得…
编程与软件工程上首页 8 次 · 2009–2025sqlite.org编辑精选高级编程语言(2009)
Advanced programming languages (2009)
Matt Might 的经典文章,按用途推荐“高级编程语言”:如果追求就业就选主流语言,如果追求表达力、学术研究或创业,则推荐 Haskell、OCaml、Scala 等函数式语…
编程与软件工程上首页 8 次 · 2009–2022matt.might.net我的 Forth 与栈机器经历
Yosefk - My history with Forth & stack machines
作者以亲身经历回顾了使用 Forth 语言和栈式机器的历程:既赞叹其简洁优雅、代码量小、可自举的优点,也坦率指出栈操作在实际编程中的痛苦,以及 Forth 社区文化中的问题。
编程与软件工程上首页 8 次 · 2010–2024yosefk.com编辑精选