簡體   English   中英

如何組合python中不同父類定義的屬性?

[英]How to combine properties defined by different parent classes in python?

假設我們有兩個類,每個類stuff以不同的方式計算屬性。 是否可以將它們的輸出組合到子類的方法/屬性中?

下面的代碼顯示了預期的效果(盡管get_stuff_from需要用適當的 python 結構替換,如果存在的話)。

class Foo():
    @property
    def stuff(self):
        return ['a','b','c']

class Bar():
    @property
    def stuff(self):
        return ['1','2','3']

class FooBar(Foo, Bar):
    @property
    def stuff(self):

        # Computes stuff from the internal state like Foo().stuff
        foo_stuff = get_stuff_from(Foo)

        # Computes stuff from the internal state like Bar().stuff
        bar_stuff = get_stuff_from(Bar)

        # Returns the combined results
        return foo_stuff + bar_stuff

foo_bar = FooBar()
print(foo_bar.stuff)

應該輸出:

['a', 'b', 'c', '1', '2', '3']

如果stuff是一個方法而不是一個屬性,這將很容易實現:

class Foo():
    def stuff(self):
        return ['a','b','c']

class Bar():
    def stuff(self):
        return ['1','2','3']

class FooBar(Foo, Bar):
    def stuff(self):

        # Computes stuff from the internal state like Foo().stuff
        foo_stuff = Foo.stuff(self)

        # Computes stuff from the internal state like Bar().stuff
        bar_stuff = Bar.stuff(self)

        # Returns the combined results
        return foo_stuff + bar_stuff

foo_bar = FooBar()
print(foo_bar.stuff())

但是,我想知道是否可以對屬性做同樣的事情。

屬性只是一個具有fget方法的對象。 您可以訪問基類的屬性對象並使用引用子類的self對象調用其fget方法:

class FooBar(Foo, Bar):
    @property
    def stuff(self):

        # Computes stuff from the internal state like Foo().stuff
        foo_stuff = Foo.stuff.fget(self)

        # Computes stuff from the internal state like Bar().stuff
        bar_stuff = Bar.stuff.fget(self)

        # Returns the combined results
        return foo_stuff + bar_stuff

現在FooBar().stuff返回['a', 'b', 'c', '1', '2', '3']

讓兩個父母為兩個不同的事物使用相同的名字是一種沖突,您應該在繼承之前解決。 通常,這意味着至少使用一個適配器類。

class Foo():
    @property
    def stuff(self):
        return ['a','b','c']

class Bar():
    @property
    def stuff(self):
        return ['1','2','3']


class BarAdaptor:
    def __init__(self):
        self.b = Bar()

    @property
    def bar_stuff(self):
        return self.b.stuff


class FooBar(Foo, BarAdaptor):
    # Don't repeat or perpetuate the mistake of
    # overloading stuff to mean different things.
    @property
    def foobar_stuff(self):
        return self.stuff + self.bar_stuff

為了對稱,您可能需要調整FooBar

這是受到將非合作類合並到合作多繼承類層次結構中的建議的啟發,在Python 的 `super() considered super! .

你可以這樣做,否則我不知道你為什么要從 Foo 和 Bar 派生。 在您當前的代碼中,您只是覆蓋了這些屬性。

class Foo():
    @property
    def stuff(self):
        return self._foo_stuff
    @property
    def _foo_stuff(self):
        return ['a','b','c']
class Bar():
    @property
    def stuff(self):
        return self._bar_stuff
    @property
    def _bar_stuff(self):
        return ['1','2','3']
class FooBar(Foo, Bar):
    @property
    def stuff(self):
        return self._foo_bar_stuff
    @property
    def _foo_bar_stuff(self):
        return self._foo_stuff + self._bar_stuff
foo_bar = FooBar()
print(foo_bar.stuff)

輸出:

['a', 'b', 'c', '1', '2', '3']

您可以使用以下代碼執行此操作

class FooBar(Foo, Bar):
    def __init__(self):
        self.foo = Foo()
        self.bar = Bar()

    @property
    def stuff(self):
        return self.foo.stuff + self.bar.stuff

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM