gpt4 book ai didi

python - super 不使用类装饰器?

转载 作者:太空狗 更新时间:2023-10-30 00:05:19 25 4
gpt4 key购买 nike

让我们定义简单的类装饰器函数,它创建子类并仅将“Dec”添加到原始类名:

def decorate_class(klass):
new_class = type(klass.__name__ + 'Dec', (klass,), {})
return new_class

现在将它应用于一个简单的子类定义:

class Base(object):
def __init__(self):
print 'Base init'

@decorate_class
class MyClass(Base):
def __init__(self):
print 'MyClass init'
super(MyClass, self).__init__()

现在,如果您尝试实例化装饰的 MyClass,它将以无限循环结束:

c = MyClass()
# ...
# File "test.py", line 40, in __init__
# super(MyClass, self).__init__()
# RuntimeError: maximum recursion depth exceeded while calling a Python object

看来,super 无法处理这种情况,并且不会从继承链中跳过当前类。

问题是,如何在使用 super 的类上正确使用类装饰器?

奖金问题,如何从 super 创建的代理对象中获取最终类? IE。从 super(Base, self).__init__ 表达式获取 object 类,作为确定的父类定义 __init__.

最佳答案

如果您只想更改类的 .__name__ 属性,请创建一个装饰器来完成该操作。

from __future__ import print_function

def decorate_class(klass):
klass.__name__ += 'Dec'
return klass

class Base(object):
def __init__(self):
print('Base init')

@decorate_class
class MyClass(Base):
def __init__(self):
print('MyClass init')
super(MyClass, self).__init__()

c = MyClass()
cls = c.__class__
print(cls, cls.__name__)

Python 2 输出

MyClass init
Base init
<class '__main__.MyClassDec'> MyClassDec

Python 3 输出

MyClass init
Base init
<class '__main__.MyClass'> MyClassDec

注意 cls 的 repr 的区别。 (虽然我不确定为什么你想要更改一个类的名称,这听起来很容易混淆,但我想对于这个简单的例子来说没问题)。

正如其他人所说,@decorator 并非旨在创建子类。您可以通过使用 super 的无参数形式(即 super().__init__())在 Python 3 中完成此操作。您可以通过显式提供父类而不是使用 super 使其在 Python 3 和 Python 2 中工作。

from __future__ import print_function

def decorate_class(klass):
name = klass.__name__
return type(name + 'Dec', (klass,), {})

class Base(object):
def __init__(self):
print('Base init')

@decorate_class
class MyClass(Base):
def __init__(self):
print('MyClass init')
Base.__init__(self)

c = MyClass()
cls = c.__class__
print(cls, cls.__name__)

Python 2 和 3 输出

MyClass init
Base init
<class '__main__.MyClassDec'> MyClassDec

最后,如果我们只是使用普通函数语法调用 decorate_class 而不是作为 @decorator 我们可以使用 super

from __future__ import print_function

def decorate_class(klass):
name = klass.__name__
return type(name + 'Dec', (klass,), {})

class Base(object):
def __init__(self):
print('Base init')

class MyClass(Base):
def __init__(self):
print('MyClass init')
super(MyClass, self).__init__()

MyClassDec = decorate_class(MyClass)
c = MyClassDec()
cls = c.__class__
print(cls, cls.__name__)

输出与上一版本相同。

关于python - super 不使用类装饰器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43659549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com