Python中的原型模式
我在Python 2.7中实现了以下原型模式:Python中的原型模式,python,design-patterns,prototype-pattern,Python,Design Patterns,Prototype Pattern,我在Python 2.7中实现了以下原型模式: def clone (instance): x = object.__new__ (type (instance)) x.__dict__ = dict (instance.__dict__) return x 这显然不适用于非新样式类(旧样式类?)和dict之类的内置类 有没有一种方法可以在Python2中清晰地将其扩展到可变的内置类型,如序列和映射类型?我认为您可以使用 deepcopy方法创建对象的1-1个副本: &
def clone (instance):
x = object.__new__ (type (instance))
x.__dict__ = dict (instance.__dict__)
return x
这显然不适用于非新样式类(旧样式类?)和dict之类的内置类
有没有一种方法可以在Python2中清晰地将其扩展到可变的内置类型,如序列和映射类型?我认为您可以使用
deepcopy
方法创建对象的1-1个副本:
>>> import copy
>>> x = [1,2,3]
>>> z = copy.deepcopy(x)
>>> x[0] = 3
>>> x
[3, 2, 3]
>>> z
[1, 2, 3]
我想你可以用
deepcopy
方法创建对象的1-1个副本:
>>> import copy
>>> x = [1,2,3]
>>> z = copy.deepcopy(x)
>>> x[0] = 3
>>> x
[3, 2, 3]
>>> z
[1, 2, 3]
你想做的是被误导了 如果您想要一份拷贝,只需使用
copy
或deepcopy
如果您想要JavaScript样式的对象,请创建一个可以克隆的根类,或者更好地用Python而不是JavaScript重新思考代码
如果你想要功能齐全的JavaScript风格的克隆,即使是内置的,你也不能这样做
<>也要记住,在java和C++等非原型语言中使用原型模式的主要动机是(a)避免<代码>新< /CODE >对象的成本,以及(b)允许向不同实例添加不同的方法或属性。对于前者,您并没有避免成本,而且在Python中这也不重要。对于后者,在Python中向实例添加方法和属性已经很容易了,而克隆并没有以任何方式让它变得更容易
我知道,与其他内置类型相比,数字类型有一些不同之处 不,这里的区别不是数字与序列,而是不变类型与可变类型:
>>> id(tuple())
4298170448
>>> id(tuple())
4298170448
>>> id(tuple(()))
4298170448
>>> id(tuple([]))
4298170448
此外,它与int
或tuple
构造函数的花式无关。如果该值未缓存在任何位置,则即使是重复的文字每次都会获得一个新实例:
>>> id(20000)
4439747152
>>> id(20000)
4439747216
小整数、空元组和不可关联的魔法常量的值在启动时被预先缓存。短字符串通常会被拘留。但具体细节取决于实现
那么,这对你有什么影响 嗯,克隆不可变类型是毫无意义的。根据定义,它是同一事物的不可更改的复制品,那么这又有什么好处呢
同时,不使用
\uuuu dict\uuuu
存储的类型不能以这种方式克隆(无论它们是内置类型、使用插槽的类型、动态生成属性的类型等等)。在某些情况下,你会得到一个错误,在其他情况下,只是错误的行为
因此,如果通过“序列、映射和数字类型”包括内置的int
和list
、stdlib类型(如Decimal
和deque
)或常见的第三方类型(如gmpy.mpz
或blist.sortedct
),则此机制将不起作用
除此之外,即使可以克隆内置类,也不能向它们添加新属性:
>>> a = []
>>> a.foo = 3
AttributeError: 'list' object has no attribute 'foo'
所以,如果你让它工作,它也不会有任何用处
同时,调用
object.\uuuuuu new\uuuu
而不是type(instance)。\uuuuu new\uuuu
可能会为不同的类带来各种问题。其中一些,如\uuuu dict\uuuu
,会给您一个错误提示,但您不能在所有情况下都依赖于此
这个想法还有其他不太严重的问题。例如:
>>> 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
你想做的是被误导了 如果您想要一份拷贝,只需使用
copy
或deepcopy
如果您想要JavaScript样式的对象,请创建一个可以克隆的根类,或者更好地用Python而不是JavaScript重新思考代码
如果你想要功能齐全的JavaScript风格的克隆,即使是内置的,你也不能这样做
<>也要记住,在java和C++等非原型语言中使用原型模式的主要动机是(a)避免<代码>新< /CODE >对象的成本,以及(b)允许向不同实例添加不同的方法或属性。对于前者,您并没有避免成本,而且在Python中这也不重要。对于后者,在Python中向实例添加方法和属性已经很容易了,而克隆并没有以任何方式让它变得更容易
我知道,与其他内置类型相比,数字类型有一些不同之处 不,这里的区别不是数字与序列,而是不变类型与可变类型:
>>> id(tuple())
4298170448
>>> id(tuple())
4298170448
>>> id(tuple(()))
4298170448
>>> id(tuple([]))
4298170448
此外,它与int
或tuple
构造函数的花式无关。如果该值未缓存在任何位置,则即使是重复的文字每次都会获得一个新实例:
>>> id(20000)
4439747152
>>> id(20000)
4439747216
小整数、空元组和不可关联的魔法常量的值在启动时被预先缓存。短字符串通常会被拘留。但具体细节取决于实现
那么,这对你有什么影响 嗯,克隆不可变类型是毫无意义的。根据定义,它是同一事物的不可更改的复制品,那么这又有什么好处呢
同时,不使用
\uuuu dict\uuuu
存储的类型不能以这种方式克隆(无论它们是内置类型、使用插槽的类型、动态生成属性的类型等等)。在某些情况下,你会得到一个错误,在其他情况下,只是错误的行为
因此,如果通过“序列、映射和数字类型”包括内置的int
和list
、stdlib类型(如Decimal
和deque
)或常见的第三方类型(如gmpy.mpz
或blist.sortedct
),则此机制将不起作用
除此之外,即使可以克隆内置类,也不能向它们添加新属性:
>>> a = []
>>> a.foo = 3
AttributeError: 'list' object has no attribute 'foo'
所以,如果你让它工作,它也不会有任何用处
同时,调用
object.\uuuuu new\uuu
而不是type(instance)。\uuuu new\uuuu
会导致