Python中有拷贝构造函数吗?如果没有,我该怎么做才能实现类似的功能?
我的情况是,我正在使用一个库,我已经通过添加额外的功能扩展了其中的一个类,并且我希望能够将从库中获取的对象转换为我自己类的实例。
Python中有拷贝构造函数吗?如果没有,我该怎么做才能实现类似的功能?
我的情况是,我正在使用一个库,我已经通过添加额外的功能扩展了其中的一个类,并且我希望能够将从库中获取的对象转换为我自己类的实例。
在Python中,可以使用默认参数定义复制构造函数。假设你想让普通构造函数运行函数non_copy_constructor(self)
,并让复制构造函数运行copy_constructor(self, orig)
。那么你可以这样做:
class Foo:
def __init__(self, orig=None):
if orig is None:
self.non_copy_constructor()
else:
self.copy_constructor(orig)
def non_copy_constructor(self):
# do the non-copy constructor stuff
def copy_constructor(self, orig):
# do the copy constructor
a=Foo() # this will call the non-copy constructor
b=Foo(a) # this will call the copy constructor
我通常实现复制构造函数的一个简单示例:
import copy
class Foo:
def __init__(self, data):
self._data = data
@classmethod
def from_foo(cls, class_instance):
data = copy.deepcopy(class_instance._data) # if deepcopy is necessary
return cls(data)
Foo.from_foo(foo)
一样工作。更进一步的改进是使其适用于Foo(foo)
,这可能是OP @Zitrax想要的。 - hobs__init__
以data
作为输入,并且对于更多类型不够灵活。2.它不允许重载。3.__init__
是公共的,如果你有其他构造函数类型,你可能不想要它。 - Gulzar针对您的情况,我建议编写一个类方法(或可以是静态方法或单独函数),它将以库类的实例为参数,并返回一个已复制所有适用属性的您自己的类实例。
__dict__
来实现吗? - hobsclass ConfusionMatrix(pd.DataFrame):
def __init__(self, df, *args, **kwargs):
try:
# Check if `df` looks like a `ConfusionMatrix`
# Could check `isinstance(df, ConfusionMatrix)`
# But might miss some "ConfusionMatrix-elligible" `DataFrame`s
assert((df.columns == df.index).all())
assert(df.values.dtype == int)
self.construct_copy(df, *args, **kwargs)
return
except (AssertionError, AttributeError, ValueError):
pass
# df is just data, so continue with normal constructor here ...
def construct_copy(self, other, *args, **kwargs):
# construct a parent DataFrame instance
parent_type = super(ConfusionMatrix, self)
parent_type.__init__(other)
for k, v in other.__dict__.iteritems():
if hasattr(parent_type, k) and hasattr(self, k) and getattr(parent_type, k) == getattr(self, k):
continue
setattr(self, k, deepcopy(v))
ConfusionMatrix
类继承了 pandas.DataFrame
,并添加了许多其他属性和方法,除非可以复制 other
矩阵数据,否则需要重新计算。我发现这个问题是通过搜索解决方案找到的。v
是一个numpy数组或导出的对象,通过使用==
进行比较会引发错误: ValueError: 无法确定具有多个元素的数组的真值。请使用a.any()或a.all()
。如果您有可能是numpy数组样式的属性,则非失败性比较(也适用于常规属性,如ints、strs等)为 np.array_equal
。 - ntjess我有一个类似的情况,不同之处在于新类只需要复制属性。因此,结合@Dunham的想法并加入一些具体性到@meisterluk的建议中,@meisterluk的“copy_constructor”方法可能是:
from copy import deepcopy
class Foo(object):
def __init__(self, myOne=1, other=None):
self.two = 2
if other <> None:
assert isinstance(other, Foo), "can only copy instances of Foo"
self.__dict__ = deepcopy(other.__dict__)
self.one = myOne
def __repr__(self):
out = ''
for k,v in self.__dict__.items():
out += '{:>4s}: {}, {}\n'.format(k,v.__class__,v)
return out
def bar(self):
pass
foo1 = Foo()
foo2 = Foo('one', foo1)
print '\nfoo1\n',foo1
print '\nfoo2\n',foo2
foo1
two: <type 'int'>, 2
one: <type 'int'>, 1
foo2
two: <type 'int'>, 2
one: <type 'str'>, one
class Entity:
def __init__(self, code=None, name=None, attrs=None):
self.code = code
self.name = name
self.attrs = {} if attrs is None else attrs
def copy(self, attrs=None):
new_attrs = {k: v.copy() for k, v in self.attrs.items()} if attrs is None else attrs
return Entity(code=self.code, name=self.name, attrs=new_attrs)
使用方法:
new_entity = entity.copy()
您可以通过以下代码实现,而无需使用任何复制模块。 Python不支持方法重载, 因此我们无法创建复制构造函数。
class student():
name: str
age: int
def __init__(self, other=None):
if other != None and isinstance(other, student):
self.name = other.name
self.age = other.age
elif not(isinstance(other,student)) and other!=None:
raise TypeError
def printInfo(s):
print(s.name, s.age)