Goo*_*ies 4 python metaclass python-2.7 python-3.x
在Python 3中,如果返回任何不是实例的值,则永远不会调用cls该__init__方法.所以我可以这样做:
class Foo:
@staticmethod
def bar(n):
return n * 5
def __new__(cls, n):
return Foo.bar(n)
print(Foo(3)) # => 15
Run Code Online (Sandbox Code Playgroud)
我的印象是订单是__call__(如果是实例) - > __new__- > __init__.
但是,在Python 2中,TypeError: this constructor takes no arguments由于缺少一个,这似乎引起了轩然大波__init__.我可以通过继承来解决这个问题object.所以,运行这个:
class Foo:
def __new__(cls, *args, **kwargs):
print("new called")
def __init__(self, *args, **kwargs):
print("init called")
Foo()
"""
Python2: "init called"
Python3: "new called"
"""
Run Code Online (Sandbox Code Playgroud)
在Python 2中,我甚至搞乱了元类.
Meta = type("Meta", (type,), dict(__call__=lambda self, x: x * 5))
class Foo(object):
__metaclass__ = Meta
print(Foo(4)) # => 20
Run Code Online (Sandbox Code Playgroud)
但这在Python3中不起作用,因为init/new方法似乎是颠倒过来的.
有没有兼容Python2/3的方法呢?
这就是我做的方式.我不喜欢它,但它有效:
class Foo(object):
@staticmethod
def __call__(i):
return i * 5
def __new__(cls, i):
return Foo.__call__(i)
Run Code Online (Sandbox Code Playgroud)
当然有更多的pythonic方式来做到这一点.
在Python 2中,您需要使用新式类来使类正常工作.这意味着您需要将您的班级定义为class Foo(object).然后你的第一个例子将在Python 2和Python 3中运行.
| 归档时间: |
|
| 查看次数: |
714 次 |
| 最近记录: |