简体   繁体   English

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

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

I want to expand the class Foo by the class Bar , the issue that I have is that I can't expand it in the usual way ( class Foo(Bar) ) because the class Bar is somewhat dynamically generated.我想通过类Bar扩展类Foo ,我遇到的问题是我无法以通常的方式( class Foo(Bar) )扩展它,因为类Bar是动态生成的。

I made this small example to illustrate my desired outcome:我做了这个小例子来说明我想要的结果:

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()

Again this is not what I'm looking for:这又不是我要找的:

class Foo(Bar):
    pass

foobar = Foo()
foobar.super_cool_function()

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

"The class Bar is somewhat dynamically generated" That's fine... as long as it follows the blueprint (of a class that should be extended by Foo ), you can leverage python closures here. “类Bar是动态生成的” 这很好……只要它遵循蓝图(应该由Foo扩展的类),您就可以在此处利用 python 闭包。 Dynamically create a new class by creating it inside, and returning it from a function.通过在内部创建并从函数返回它来动态创建一个新类。

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

    return Foo

DynamicFoo = get_class(Bar)
myobj = DynamicFoo()

This is a common pattern you'll see in python - leveraging closures to dynamically create callbacks and classes.这是您将在 python 中看到的常见模式 - 利用闭包动态创建回调和类。


The answer above assumes that Bar is correctly defined, when it in fact is not.上面的答案假定Bar已正确定义,但实际上并非如此。 The super_cool_function is missing a self parameter. super_cool_function缺少 self 参数。 Instance methods are always called with the first parameter (the instance itself) automatically being passed in as the first attribute.实例方法总是使用第一个参数(实例本身)自动作为第一个属性传入。

So, the correct definition for Bar would be:因此, Bar的正确定义是:

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

Now, defining get_class with the simplest definition of the inner class Foo :现在,使用内部类Foo的最简单定义来定义get_class

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

    return Foo

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

Your desired use is a little strange:你想要的用途有点奇怪:

foobar = Foo(Bar)

You're constructing a Foo instance by handing it the Bar class object, and expecting to get back something that acts like a Bar instance.您正在通过将Bar类对象交给它来构造Foo实例,并期望得到一些类似于Bar实例的东西。 Normally, a proxy class is designed to take an object to proxy to, or look on up somewhere, not just construct one with no arguments.通常,代理类旨在将对象代理到或查找某处,而不仅仅是构造一个没有参数的对象。

But, other than that oddness, which just means an __init__ method that constructs the object, this is just a bog-standard proxy class.但是,除了那个奇怪的东西,它只是意味着构造对象的__init__方法,这只是一个沼泽标准的代理类。 So:所以:

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)

Of course you still won't be able to call that super_cool_function on a foobar any more than you could on a Bar instance, because it's defined as a method and doesn't have a self parameter.当然,您仍然无法super_cool_functionBar实例上super_cool_functionfoobar上调用super_cool_function ,因为它被定义为方法并且没有self参数。 But you'll get the same error from the Foo instance that you would have gotten from a Bar instance:但是您将从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