Python:创建幂等初始值设定项
在python中创建幂等初始值设定项的正确方法是什么?所谓幂等元,我的意思是,如果objectPython:创建幂等初始值设定项,python,python-3.x,Python,Python 3.x,在python中创建幂等初始值设定项的正确方法是什么?所谓幂等元,我的意思是,如果objectx是类A的实例,那么A(x)就是x(类似于正则表达式模式、冻结集、字符串和元组)。我可以想出三种解决办法: 覆盖新的 class A: def __new__(cls, *args, **kwargs): if not kwargs and len(args) == 1 and isinstance(args[0],cls): return args[0] return
x
是类A
的实例,那么A(x)就是x
(类似于正则表达式模式、冻结集、字符串和元组)。我可以想出三种解决办法:
class A:
def __new__(cls, *args, **kwargs):
if not kwargs and len(args) == 1 and isinstance(args[0],cls):
return args[0]
return super().__new__(*args, **kwargs)
def __init__(*args, **kwargs):
# check that init isn't called on the same object twice
if not kwargs and len(args) == 1 and isinstance(args[0],cls):
return
... # actual initialization goes here
class A:
...
def a(*args, **kwargs):
if not kwargs and len(args) == 1 and isinstance(args[0], A):
return args[0]
return A(*args, **kwargs)
class Meta(type):
def __call__(cls, *args, **kwargs):
if not kwargs and len(args) == 1 and isinstance(args[0], cls):
return args[0]
return super().__call__(*args, **kwargs)
class A(metaclass = Meta):
...
对我来说,所有这些解决方案似乎都很老套,而且每个都有明显的缺点。做这件事的方法是什么规范的方法是让
\uuuuu new\uuuu
返回对象本身。这正是frozenset
、字符串和元组所做的,尽管是在C代码中
例如,frozenset.\uuuuu new\uuuuu
是使用:
/* frozenset(f) is idempotent */
if (PyFrozenSet_CheckExact(iterable)) {
Py_INCREF(iterable);
return iterable;
}
考虑到这些是不可变的类型,因此它们不定义\uuuu init\uuu
方法(或等效的C)。这很重要,因为从\uuuu new\uuuu
返回作为当前类(或子类)实例的对象将自动触发\uuuu init\uuuu
,如果已定义,则将调用该对象。您不希望在此处重新初始化对象
因此,正确的实现将把所有内容放入\uuuuu new\uuuu
:
很好的回答,谢谢。虽然我要说的是,我确实确保了init方法不会影响以这种方式返回的对象。@Bentheii:我知道,但这只是在不可变对象上使用
\uuuu init\uuu
的一种变通方法。
class A:
def __new__(cls, *args, **kwargs):
if not kwargs and len(args) == 1 and isinstance(args[0], cls):
# A(instance_of_A) is idempotent
return args[0]
instance = super().__new__(*args, **kwargs)
# actual initialization goes here
return instance
# **NO** __init__ method for 'immutable' objects