代码:
import functools
class MyInt1(int):
def __new__(cls, x, value):
print("MyInt1.__new__", cls, x, value)
return super().__new__(cls, x, base=2)
def __init__(self, x, value):
print("MyInt1.__init__", self, x, value)
self.value = value
super().__init__()
class MyInt2:
def __init__(self, x, value):
print("MyInt2.__init__", self, x, value)
self.value = value
def decorator(class_):
class Wrapper(class_):
def __new__(cls, *args, **kwargs):
print("Wrapper.__new__", cls, args, kwargs)
obj = super().__new__(cls, *args, **kwargs)
...
return obj
def __init__(self, *args, **kwargs):
print("Wrapper.__init__", self, args, kwargs)
functools.update_wrapper(self, class_)
super().__init__(*args, **kwargs)
return Wrapper
c = decorator(MyInt1)("101", 42)
print(c, c.value)
c = decorator(MyInt2)("101", 42)
print(c, c.value)
输出:
Wrapper.__new__ <class '__main__.decorator.<locals>.Wrapper'> ('101', 42) {}
MyInt1.__new__ <class '__main__.decorator.<locals>.Wrapper'> 101 42
Wrapper.__init__ 5 ('101', 42) {}
MyInt1.__init__ 5 101 42
5 42
Wrapper.__new__ <class '__main__.decorator.<locals>.Wrapper'> ('101', 42) {}
Traceback (most recent call last):
File "tmp2.py", line 42, in <module>
c = decorator(MyInt2)("101", 42)
File "tmp2.py", line 28, in __new__
obj = super().__new__(cls, *args, **kwargs)
TypeError: object() takes no parameters
__new__
不接受__init__
参数?我找到的唯一方法是inspect.isbuiltin
检查super().__new__
并进行分支,但这很脏。
答案 0 :(得分:1)
很难找到有关Python的基类(对象)行为的详细信息,这些行为是为了在创建新类时仅实现document.getElementById("testdiv").innerHTML = "<img src=" + test1.par2 + "alt=" + test1.par1 + " class='image' />";
而实现的:
document.getElementById("testdiv").innerHTML = `<img src=${test1.par2} alt=${test1.par1} class='image' />`;
和__init__
之外, object
自己的__init__
和__new__
方法不会引用任何争议。但是 - 如果从子类调用它们(碰巧是Python中定义的所有其他类) - 这些方法的每个方法都检查子类是否定义了一个而不是另一个(即,对象&#39; s {{ 1}}检查被实例化的类是否也定义了self
。
如果任何一个方法发现converse方法已被覆盖而且本身没有,它只是吞下任何额外的参数:因此用户的类cls
可以有参数,而不用担心相同的参数 - 将传递给__init__
将导致错误,
因此,您遇到的问题是,在此检查期间,例如,对象的__new__
发现您的包装器已定义__init__
- 因此它不会吞下任何参数 - 和错误,因为有额外的论点。
修复它的唯一方法是,如果要保持这种模式,就是在装饰器中重新实现相同的逻辑:
object.__new__
https://mail.python.org/pipermail/python-list/2016-March/704027.html表明存在这种行为的暗示 - 我在官方文档中看起来似乎是这样,但在某些地方我不记得哪一个。