我在 Python 2.7 中有以下原型模式的实现:
def clone (instance):
x = object.__new__ (type (instance))
x.__dict__ = dict (instance.__dict__)
return x
这显然不适用于非新式类(旧式类?)和像 dict 这样的内置函数。
有没有办法,干净地留在 Python 2 中,将其扩展到可变的内置类型,如序列和映射类型?
我在 Python 2.7 中有以下原型模式的实现:
def clone (instance):
x = object.__new__ (type (instance))
x.__dict__ = dict (instance.__dict__)
return x
这显然不适用于非新式类(旧式类?)和像 dict 这样的内置函数。
有没有办法,干净地留在 Python 2 中,将其扩展到可变的内置类型,如序列和映射类型?
我认为您可以使用复制模块
该deepcopy方法创建对象的 1-1 副本:
>>> import copy
>>> x = [1,2,3]
>>> z = copy.deepcopy(x)
>>> x[0] = 3
>>> x
[3, 2, 3]
>>> z
[1, 2, 3]
it from book Python in practice Book by Mark Summerfield you can create copy of object
class Point:
__slots__ = ("x", "y")
def __init__(self, x, y):
self.x = x
self.y = y
def make_object(Class,*args,**kwargs):
return Class(*args,**kwargs)
point1 = Point(1, 2)
point2 = eval("{}({}, {})".format("Point", 2, 4)) # Risky
point3 = getattr(sys.modules[__name__], "Point")(3, 6)
point4 = globals()["Point"](4, 8)
point5 = make_object(Point, 5, 10)
point6 = copy.deepcopy(point5)
point6.x = 6
point6.y = 12
point7 = point1.__class__(7, 14) # Could have used any of point1 to point6
schema and example of use code you can read on tutorialspoint, it for java, but principle is comprehensible
你试图做的事情是被误导的。
如果您只想要一个副本,只需使用copyor deepcopy。
如果您想要 JavaScript 样式的对象,请创建一个可以克隆的根类,或者更好的是,用 Python 而不是 JavaScript 重新考虑您的代码。
如果你想要功能齐全的 JavaScript 风格的克隆,即使是内置的,你也不能这样做。
此外,请记住,在 Java 和 C++ 等非基于原型的语言中使用原型模式的主要动机是(a)避免new构建对象的成本,以及(b)允许添加不同的方法或属性不同的实例。对于前者,您并没有避免成本,而且在 Python 中也没关系。对于后者,在 Python 中向实例添加方法和属性已经很容易了,而克隆并没有让它变得更容易。
我知道与其他内置类型相比,数字类型有一些不同的地方......</p>
不,这里的区别不是数字与序列,而是不可变类型与可变类型:
>>> id(tuple())
4298170448
>>> id(tuple())
4298170448
>>> id(tuple(()))
4298170448
>>> id(tuple([]))
4298170448
int此外,它与ortuple构造函数的花哨无关。如果该值没有缓存在任何地方,即使是重复的文字每次都会获得一个新实例:
>>> id(20000)
4439747152
>>> id(20000)
4439747216
小整数、空元组和不可分配的魔法常量的值在启动时被预先缓存。短字符串通常会被拘留。但具体细节取决于实现。
那么,这对您有何影响?
好吧,克隆不可变类型是没有意义的。根据定义,它是同一事物的不可更改副本,那有什么好处呢?
同时,__dict__不能以这种方式克隆不用于存储的类型(无论它们是内置类型、使用槽的类型、动态生成其属性的类型……)。在某些情况下你会得到一个错误,在其他情况下只是错误的行为。
因此,如果通过“序列、映射和数字类型”包含诸如 and 之类的内置函数、诸如andint之list类的 stdlib 类型或诸如or之类的常见第三方类型,那么此机制将不起作用。Decimaldequegmpy.mpzblist.sorteddict
最重要的是,即使您可以克隆内置类,也不能向它们添加新属性:
>>> a = []
>>> a.foo = 3
AttributeError: 'list' object has no attribute 'foo'
所以,如果你让它再次工作,它无论如何都不会有用。
同时,调用object.__new__而不是type(instance).__new__可能会导致不同类的各种问题。其中一些,比如__dict__,会给你一个错误告诉你,但你不能在每种情况下都指望它。
这个想法还有其他不那么严重的问题。例如:
>>> class Foo(object):
... def __init__(self):
... self.__private = 3
>>> foo = Foo()
>>> foo.__private
3
>>> bar = clone(foo)
>>> bar.__private
AttributeError: 'Foo' object has no attribute '__private'
>>> bar._Foo__private
3