Python 如何将构造函数方法传递给另一个方法并在那里调用它?
我试图避免在两个类的克隆方法中重复相同的代码,一个从另一个继承。我目前的方法是将两个类共有的代码放在基类的(非静态)克隆方法中,并从扩展类调用它。为此,我试图将扩展类的构造函数传递给基类,以便在基类中调用它。以下是我目前正在做的一个简化示例:Python 如何将构造函数方法传递给另一个方法并在那里调用它?,python,inheritance,methods,Python,Inheritance,Methods,我试图避免在两个类的克隆方法中重复相同的代码,一个从另一个继承。我目前的方法是将两个类共有的代码放在基类的(非静态)克隆方法中,并从扩展类调用它。为此,我试图将扩展类的构造函数传递给基类,以便在基类中调用它。以下是我目前正在做的一个简化示例: class S(object): """Base class""" def __init__(self): self.a = 0 def clone(self, constructor=None):
class S(object):
"""Base class"""
def __init__(self):
self.a = 0
def clone(self, constructor=None):
if constructor is None:
constructor = self.__init__
cloned = constructor()
# Expecting: cloned.a = 1, cloned.b = 7
assert cloned is not None # raises AssertionError
cloned.a = self.a # Set a to 2
return cloned
class C(S):
"""Child class, extending Base"""
def __init__(self):
self.a = 1
self.b = 7
def clone(self):
cloned = super(C, self).clone(self.__init__)
# Expecting: cloned.a = 2, cloned.b = 7
cloned.b = self.b # Set b to 8
return cloned
if __name__ == '__main__':
c1 = C()
c1.a = 2
c1.a = 8
c2 = c1.clone()
在这一点上,我的问题是:
- 为什么调用基类的
方法时返回clone
None
- 我是否必须将该方法绑定到类才能使用它
或types.MethodType
获取
- 你有什么更好的建议吗
\uuu init\uuu()
通常被称为构造函数,但实际上不是。它获取作为self
参数传入的实例,并返回None
。该实例在前面由\uuuuu new\uuuu()
方法构造,该方法是实际的构造函数。不过,您不应该传入对\uuuu new\uuu
的引用。传入类型本身更容易、更直接
Edit:实现
clone
方法的正确方法是另一种方法:坚持通常的Python协议,在实例上实现and。然后,您可以使用copy
模块中的函数正确克隆实例。您的基类克隆方法是多余的。从任何上下文调用self.\uuuu init\uuu()
都将遵循对象特定实例的MRO,这意味着在C
的实例上调用clone()
将从S
中的代码调用C.\uu init\uuuuu()
,而无需明确指定使用C.\uu init\uuuu()
如果您想做的是能够自定义clone()
,而不必创建一个全新的类,或者根据其他因素有不同的行为,我建议查看factory/builder模式
另外,特别是对于
clone()
类型操作,您可能需要查看重载\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
而不是实施一个新的辩证元素。你知道复制
模块吗?@KarlKnechtel:是的,但我做了一些错误的假设,使我认为它不足以满足我所要做的。事实证明是这样的。在其他语言中,构造函数也在已分配内存和已构造但未初始化对象的上下文中运行。在\uuuu init\uuuu
中,它不是构造函数到底有什么不同?O_o@BartoszKP这个问题的主旨是希望构造函数生成一个新的对象并返回它,但它没有,我的回答是要说明这一点。也就是说,在C++中,代码的作用肯定有差异。最重要的区别是,\uuuu new\uuu()
已经以一致的状态返回一个完全工作的对象,在某些情况下甚至是一个初始化的对象(例如,对于不可变类型)\uuuuu init\uuuuu
,因此在这种情况下我不会称它为“完全工作”。@BartoszKP我不会坚持使用这个术语-调用\uuuuu init\uuuuuuu()
构造函数和\uuuuu new\uuuuuuuuu()
构造函数都是合理的。这个答案中的措辞可能过于强硬,但我并不在意——我主要是想回答老年退休金计划的问题。你是对的,我承认这是一个区别(不是很大,但值得一提)。而且,这正是文档所说的(这两个函数一起作为构造函数工作):)干杯!