簡體   English   中英

如何在 python 中參數化 Mixins,而不顯式調用它們的構造函數?

[英]How can I parameterize Mixins in python, without calling their constructor explicitly?

我想在 python 中更多地使用 Mixins 並且喜歡以下模式:

class Person:
  [...]

class Greetable:
  greeting: str

  def __init__(*args, **kwargs):
    super().__init(*args, **kwargs)
    ... greeting related setup

  def greet(self):
    print(f"{self.greeting} sir or madam!")

class Sailor(Greetable, Person):
  def __init__(self):
    super().__init__()

    self.greeting = "Ahoy"

>>> Sailor().greet()
"Ahoy sir or madam!"

但是我還沒有解決參數化mixin的問題。 在我的工作中,我看到很多對超類的顯式__init__調用 alá

class A(B, FloorMixin):
  def __init__(desk, chair, floor):
    B.__init__(self, desk, chair)
    FloorMixin.__init__(floor)

我看到了分解參數並顯式分配它們的用途,但我想保留上述 Mixin 示例的__init__具有的“passthrough”屬性。

我只能想到將 Mixin 的所有參數作為特定的關鍵字參數,這些參數會從**kwargs參數中pop ,或者只依賴於 mixin 中存在的字段並且必須在之前設置它們,這將變成最后一個例如到:

class A(FloorMixin, B):
  def __init__(desk, chair, floor):
    self._floor = floor  # FloorMixin expects a _floor attribute

    super().__init__(desk, chair)

正確使用super的關鍵是層次結構中涉及的每個類都應該假設其他人也會調用super 對於除object之外的每個類都是如此,它始終是任何繼承層次結構中的根類。

對於你的例子

class A(B, FloorMixin):
  def __init__(self, desk, chair, floor):
    B.__init__(self, desk, chair)
    FloorMixin.__init__(floor)

這意味着ABFloorMixin都應該調用super().__init__ ,並且在實例化A時應該使用關鍵字參數,以便沒有基於排序的沖突。

class B:
    def __init__(self, desk, chair, **kwargs):
        super().__init__(**kwargs)
        # Do stuff with desk and chair

class FloorMixin:
    def __init__(self, floor, **kwargs):
        super().__init__(**kwargs)
        # Do stuff with floor

class A(B, FloorMixin):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # If there's nothing else to do, you don't
        # even need to define A.__init__

# With keyword arguments, order doesn't matter
# Each __init__ will find the arguments it needs
# and pass on the rest
a = A(floor="...", chair="...", desk="...")

A的方法解析順序是[A, B, FloorMixin, object] ,因此每次調用super().__init__ __init__從行中的下一個類調用__init__ A.__init__調用B.__init__ ,后者調用FloorMixin.__init__ ,后者調用object.__init__ 重要的是,請注意,這意味着在運行時B.__init__調用B的作者甚至可能不知道的類的__init__ 這就是為什么接受意外的關鍵字參數並傳遞它們很重要的原因。

暫無
暫無

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

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