Python:强制新式类
我希望这段代码“正常工作”:
def main():
c = Castable()
print c/3
print 2-c
print c%7
print c**2
print "%s" % c
print "%i" % c
print "%f" % c
当然,最简单的方法是编写 int(c)/3
,但我想为配置启用更简单的 perl-ish 语法迷你语言。
值得注意的是,如果我使用“旧式”类(不从对象继承),我可以通过定义 __coerce__ 方法来非常简单地做到这一点,但旧式类已被弃用,并且将被在 python3 中删除了。
当我对新式类做同样的事情时,我收到此错误:
TypeError: unsupported operand type(s) for /: 'Castable' and 'int'
我相信这是设计使然,但是如何用新式类模拟旧式 __coerce__ 行为?您可以在下面找到我当前的解决方案,但它非常丑陋且冗长。
这是相关文档:(我认为)
奖励积分:
print pow(c, 2, 100)
I want this code to "just work":
def main():
c = Castable()
print c/3
print 2-c
print c%7
print c**2
print "%s" % c
print "%i" % c
print "%f" % c
Of course, the easy way out is to write int(c)/3
, but I'd like to enable a simpler perl-ish syntax for a configuration mini-language.
It's notable that if I use an "old-style" class (don't inherit from object) I can do this quite simply by defining a __coerce__
method, but old-style classes are deprecated and will be removed in python3.
When I do the same thing with a new-style class, I get this error:
TypeError: unsupported operand type(s) for /: 'Castable' and 'int'
I believe this is by design, but then how can I simulate the old-style __coerce__
behavior with a new-style class? You can find my current solution below, but it's quite ugly and long-winded.
This is the relevant documentation: (i think)
Bonus points:
print pow(c, 2, 100)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果你想让
c/3
工作,你需要定义__div__
。 Python 不会先为您将对象转换为数字。You need to define
__div__
if you wantc/3
to work. Python won't convert your object to a number first for you.这是有效的,并且经过几次改进(支持@jchl)后不再那么粗糙,但似乎仍然是不必要的,特别是考虑到你可以通过“旧式”课程免费获得它。
我仍在寻找更好的答案。如果没有更好的方法,在我看来这就像Python语言的回归。
This works, and is less gross after several improvements (props to @jchl), but still seems like it should be unecessary, especially considering that you get this for free with "old-style" classes.
I'm still looking for a better answer. If there's no better method, this seems to me like a regression in the Python language.
新样式的类比旧样式的类运行得更快、更精确。因此,不会因为任何廉价的原因并且以有问题的顺序进行更昂贵的 __getattr__ 、 __getattribute__ 、 、 __coerce__ 调用。
旧样式 __coerce__ 也存在问题,即使您已经出于某种特殊目的重载了运算符方法,它也会被调用。它要求转换为相同的常见类型,并且仅限于某些二进制操作。想想 int / float / string 的所有其他方法和属性 - 以及 pow()。由于所有这些限制,PY3 中缺少
coerce
。问题示例针对相当广泛的虚拟化。对于新样式的类,它只是一个循环,用很少的代码提供许多“类似”的方法,或者将这些调用路由到虚拟处理程序,然后以正确和细粒度的方式快速、精确地定义和子类化。这不是“Python 语言的回归”。
但是,我不会仅仅为了这样的循环或提供简单的基类行为而采用其他答案中所示的元类。这无异于用大锤敲碎坚果。
这里是一个“变体”虚拟化的示例助手:
这里是一个示例用例:Anaphor! (PY2 和 PY3):
它还无缝处理 3-arg 运算符
pow()
:-) :New style classes operate faster and more precise than old style classes. Thus no more expensive
__getattr__
,__getattribute__
,__coerce__
calls for any cheap reasons and in a questionable order.The old style
__coerce__
also had the problem, that it was called even when you have already overloaded an operator method for some special purpose. And it demands casting to equal common types, and is limited to certain binary ops. Think about all the other methods and properties of an int / float / string - and about pow(). Due to all these limitationscoerce
is missing in PY3. The question examples aim at rather wide virtualization.With new style classes its just about a loop to provide many "similar" methods with little code, or route those calls to a virtual handler and then its fast and precisely defined and subclassable in correct and fine grained manner. Thats not a "regression in the Python language".
However I would not employ a meta class as shown in other answers just for such a loop or for providing a simple base class kind of behavior. That would be cracking a nut with a sledgehammer.
Here an example helper for virtualization of a "variant":
And here an example use case: An Anaphor! (PY2 and PY3) :
Seamlessly it also handles the 3-arg opertor
pow()
:-) :