繁体   English   中英

是否可以从仅在python运行时已知的类动态继承?

[英]Is it possible to dynamically inherit from a class that is only known at runtime in python?

我想通过类Bar扩展类Foo ,我遇到的问题是我无法以通常的方式( class Foo(Bar) )扩展它,因为类Bar是动态生成的。

我做了这个小例子来说明我想要的结果:

class Bar:
    def super_cool_function():
        print("Cool")

class Foo:
    def __init__(self, another_class):
        # I want to extend Foo by another_class

# Desired result
foobar = Foo(Bar)
foobar.super_cool_function()

这又不是我要找的:

class Foo(Bar):
    pass

foobar = Foo()
foobar.super_cool_function()

TL;DR:是的,使用 python 闭包

“类Bar是动态生成的” 这很好……只要它遵循蓝图(应该由Foo扩展的类),您就可以在此处利用 python 闭包。 通过在内部创建并从函数返回它来动态创建一个新类。

def get_class(superclass):
    class Foo(superclass):
        def __init__(self, ...):
           ...

    return Foo

DynamicFoo = get_class(Bar)
myobj = DynamicFoo()

这是您将在 python 中看到的常见模式 - 利用闭包动态创建回调和类。


上面的答案假定Bar已正确定义,但实际上并非如此。 super_cool_function缺少 self 参数。 实例方法总是使用第一个参数(实例本身)自动作为第一个属性传入。

因此, Bar的正确定义是:

class Bar:
   def super_cool_function(self):
       print("Cool")

现在,使用内部类Foo的最简单定义来定义get_class

def get_class(superclass):
    class Foo(superclass):
        pass

    return Foo

DynamicFoo = get_class(Bar)
myobj = DynamicFoo()
myobj.super_cool_function()
# Cool

你想要的用途有点奇怪:

foobar = Foo(Bar)

您正在通过将Bar类对象交给它来构造Foo实例,并期望得到一些类似于Bar实例的东西。 通常,代理类旨在将对象代理到或查找某处,而不仅仅是构造一个没有参数的对象。

但是,除了那个奇怪的东西,它只是意味着构造对象的__init__方法,这只是一个沼泽标准的代理类。 所以:

class Foo:
    def __init__(self, cls):
        self._inst = cls()
    def __getattr__(self, name):
        return getattr(self._inst, name)
    def __setattr__(self, name, value):
        if name in {'_inst'}:
            super().__setattr__(name, value)
        else:
            setattr(self._inst, name, value)
    def __delattr__(self, name):
        delattr(self._inst, name)

当然,您仍然无法super_cool_functionBar实例上super_cool_functionfoobar上调用super_cool_function ,因为它被定义为方法并且没有self参数。 但是您将从Foo实例中得到与从Bar实例中得到的相同的错误:

>>> foobar.super_cool_function
<bound method Bar.super_cool_function of <__main__.Bar object at 0x129f95080>>
>>> foobar.super_cool_function()
TypeError: super_cool_function() takes 0 positional arguments but 1 was 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM