簡體   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