如何对“ super()”进行故障排除。
我的库中有一个装饰器,该装饰符上用户的类并创建了一个新版本,并使用新的元素段,应该完全替换原始类。一切都起作用;除super()
调用外:
class NewMeta(type):
pass
def deco(cls):
cls_dict = dict(cls.__dict__)
if "__dict__" in cls_dict:
del cls_dict["__dict__"]
if "__weakref__" in cls_dict:
del cls_dict["__weakref__"]
return NewMeta(cls.__name__, cls.__bases__, cls_dict)
@deco
class B:
def x(self):
print("Hi there")
@deco
class A(B):
def x(self):
super().x()
使用此代码,会产生错误:
>>> a = A()
>>> a.x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in x
TypeError: super(type, obj): obj must be an instance or subtype of type
某些术语:
- 源代码类
a
由a(b)类产生:
。 - 由
newmeta(Cls .__ name__,cls .__ bases__,cls_dict)生成的类别的类
a*
。
A
由Python建立为type
当在a*a*
的方法中使用super
时。我该如何纠正?
有一些次优的解决方案,例如调用super(type(self),self).x
,或通过cls .__ mro __
而不是cls .__ bases __ bases __
进入newMeta
呼叫(以便obj = self
总是从错误的type = a
)继承。对于最终用户来说,第一个是不可持续的,第二个污染了继承链,并且由于班级似乎从自身继承而感到困惑。
Python似乎是内省的源代码,或者可能存储一些信息以自动建立type
,在这种情况下,我会说它没有做到;
我如何确保在a
A*
的方法内建立为type
gongeless grognless super
super 呼叫?
I have a decorator in my library which takes a user's class and creates a new version of it, with a new metaclass, it is supposed to completely replace the original class. Everything works; except for super()
calls:
class NewMeta(type):
pass
def deco(cls):
cls_dict = dict(cls.__dict__)
if "__dict__" in cls_dict:
del cls_dict["__dict__"]
if "__weakref__" in cls_dict:
del cls_dict["__weakref__"]
return NewMeta(cls.__name__, cls.__bases__, cls_dict)
@deco
class B:
def x(self):
print("Hi there")
@deco
class A(B):
def x(self):
super().x()
Using this code like so, yields an error:
>>> a = A()
>>> a.x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in x
TypeError: super(type, obj): obj must be an instance or subtype of type
Some terminology:
- The source code class
A
as produced byclass A(B):
. - The produced class
A*
, as produced byNewMeta(cls.__name__, cls.__bases__, cls_dict)
.
A
is established by Python to be the type
when using super
inside of the methods of A*
. How can I correct this?
There's some suboptimal solutions like calling super(type(self), self).x
, or passing cls.__mro__
instead of cls.__bases__
into the NewMeta
call (so that obj=self
always inherits from the incorrect type=A
). The first is unsustainable for end users, the 2nd pollutes the inheritance chains and is confusing as the class seems to inherit from itself.
Python seems to introspect the source code, or maybe stores some information to automatically establish the type
, and in this case, I'd say it is failing to do so;
How could I make sure that inside of the methods of A
A*
is established as the type
argument of argumentless super
calls?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
无参数
super
使用__类__
单元格,这是常规函数闭合。像任何其他关闭一样,这是词汇关系:它是指从字面上定义该方法的
class
范围。用装饰师代替班级仍然具有原始类的方法。最简单的修复方法是明确提及类的名称,该名称 由装饰者反弹到新创建的类。
另外,人们可以更改
__类__
单元格的内容以指向新类:The argument-free
super
uses the__class__
cell, which is a regular function closure.Like any other closure, this is a lexical relation: it refers to
class
scope in which the method was literally defined. Replacing the class with a decorator still has the methods refer to the original class.The simplest fix is to explicitly refer to the name of the class, which gets rebound to the newly created class by the decorator.
Alternatively, one can change the content of the
__class__
cell to point to the new class: