簡體   English   中英

在Python 3中,超類可以多態調用子類的構造函數

[英]in Python 3, can a superclass polymorphically call a subclass's constructor

我想在一個類( Parent )中創建方法(例如copy ),該方法將返回該類調用它的子類的對象。 我想要type(x) == type(x.copy())

我嘗試的所有方法均未令人滿意。

  • 使用超類構造函數將返回超類(有道理,但我認為值得嘗試)。
  • 在超類使用的每個子類中創建一個函數init_me ,但這樣做init_me了繼承的目的。
  • 我開始探索__new____init__ ,但是很快決定Python必須有更好的方法。

樣例代碼

class Parent(object):
    def __init__(self, p1=p1_default, p2=p2_default, p3=p3_default):
        ...   # common stuff
        self._special_suff()
    def copy_works_if_subclass_does_extra(self):
        return self.init_me()
    def copy_only_does_superclass(self):
        return Parent()
    def copy_with_init(self):
        return self.__init__()
    def whoami(self):
        print('I am just a parent')

class Dad(Parent):
    def _special_stuff():
        ...     # Dad special stuff
        return 
    def whoami(self):
        print('I am a dad')
    def init_me(self):
        return Dad()

class Mom(Parent):
    def _special_stuff():
        ...     # Mom special stuff
        return 
    def whoami(self):
        print('I am a mom')

如果我理解正確,您正在嘗試在基類中編寫一個copy方法,該方法在派生類的實例上調用時仍然可以使用。 這可以使它起作用,但是只有當您的子類只期望與基類具有相同的參數集時,這才容易。 如果他們的__init__方法期望使用不同的參數,則需要為每個派生類使用單獨的copy方法。

這是一個如何工作的簡單示例。 訣竅是調用type(self)以獲取正確的類,然后使用適當的構造函數參數調用該類以獲取新實例:

class Base(object):
    def __init__(self, arg1, arg2, arg3):
        self.attr1 = arg1
        self.attr2 = arg2
        self.attr3 = arg3

    def copy(self):
        cls = type(self)
        return cls(self.attr1, self.attr2, self.attr3)

class Derived(Base):
    def __init__(self, arg1, arg2, arg3):
        super().__init__(arg1, arg2, arg3)
        self.some_other_attr = "foo"

在實踐中,這往往效果不佳,因為Derived類通常希望使用額外的參數來設置其額外屬性。 在這種情況下可能有效的選擇是使用copy模塊,而不是編寫自己的copy方法。 函數copy.copy將能夠復制許多Python實例,而無需任何特殊支持。

您使事情復雜化了很多 在子類上實現了一個簡單構造函數的最小示例:

import copy

class Parent():
    def whoami(self):
        print('Just a parent')
    def __init__(self, name):
        self.name = name
    def copy(self):
        # Maybe copy.deepcopy instead
        return copy.copy(self)


class Dad(Parent):
    def whoami(self):
        print('I am a dad')
    def __init__(self, name):
        super().__init__(name)
        self.gender = 'Male'

如果不需要,甚至不需要使用Python中的構造函數。 或者,您可以在超類上擁有一個,而在子類上則沒有。

一些用法:

>>> dad = Dad("Clark Griswold")
>>> dad.name
'Clark Griswold'
>>> dad.whoami()
I am a dad
>>> isinstance(dad, Dad)
True
>>> isinstance(dad, Parent)
True
>>> type(dad.copy()) == type(dad)
True

暫無
暫無

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

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