python创建两个圆对象_如何在Python中创建第二个None?制作id始终相同的单例对象...

警告:以下问题是有关不良做法和肮脏代码的信息.建议开发人员谨慎.

注意:这与Creating a singleton in Python问题不同,因为我们要解决酸洗和复制以及普通对象的创建问题.

目标:我想创建一个值(称为NoParam)来模拟None的行为.具体来说,我希望NoParamType的任何实例都具有相同的值-即具有相同的ID-以便is运算符始终在其中两个值之间返回True.

原因:我拥有可保留参数值的配置类.其中一些参数可以将None作为有效类型.但是,如果没有指定类型,我希望这些参数采用特定的默认值.因此,我需要一些不是None的哨兵来指定未指定任何参数.这个哨兵应该是

?永远不能用作有效的参数值.我希望对此哨兵有一个特殊的类型,而不是使用一些不太可能使用的字符串.

例如:

def add_param(name, value=NoParam):

if value is NoParam:

# do some something

else:

# do something else

但是,不必为此担心太多.让我们专注于如何.

到目前为止,我有:

我可以轻松实现大多数这种行为.我创建了一个名为util_const.py的特殊模块.它包含一个创建NoParamType的类,然后创建该类的单例实例.

class _NoParamType(object):

def __init__(self):

pass

NoParam = _NoParamType()

我只是假设永远不会创建此类的第二个实例.每当我想使用该值时,我都会导入util_const并使用util_const.NoParam.

这在大多数情况下效果很好.但是,我只是遇到一个情况

将NoParam值设置为对象值.使用copy.deepcopy深度复制了对象,因此创建了第二个NoParam实例.

我通过定义__copy__和__deepcopy__方法找到了一个非常简单的解决方法

class _NoParamType(object):

def __init__(self):

pass

def __copy__(self):

return NoParam

def __deepcopy__(self, memo):

return NoParam

NoParam = _NoParamType()

现在,如果将Deepcopy称为noNoParam,则仅返回现有的NoParam实例.

现在问题是:

我可以做些什么来实现与酸洗相同的行为吗?最初,我以为可以定义__getstate__,但是第二个实例已经在该点创建了.本质上,我希望pickle.loads(pickle.dumps(NoParam))是NoParam以返回True.有没有办法做到这一点(也许使用元类)?

更进一步:我可以做些什么来确保仅创建一个NoParam实例?

非常感谢@ user2357112回答了有关酸洗的问题.

我还想出了如何使此类对模块重新加载也很健壮.这是我所学到的全部内容

# -*- coding: utf-8 -*-

# util_const.py

class _NoParamType(object):

"""

Class used to define `NoParam`, a setinal that acts like None when None

might be a valid value. The value of `NoParam` is robust to reloading,

pickling, and copying.

Example:

>>> import util_const

>>> from util_const import _NoParamType, NoParam

>>> from six.moves import cPickle as pickle

>>> import copy

>>> versions = {

... 'util_const.NoParam': util_const.NoParam,

... 'NoParam': NoParam,

... '_NoParamType()': _NoParamType(),

... 'copy': copy.copy(NoParam),

... 'deepcopy': copy.deepcopy(NoParam),

... 'pickle': pickle.loads(pickle.dumps(NoParam))

... }

>>> print(versions)

>>> assert all(id(v) == id_ for v in versions.values())

>>> import imp

>>> imp.reload(util_const)

>>> assert id(NoParam) == id(util_const.NoParam)

"""

def __new__(cls):

return NoParam

def __reduce__(self):

return (_NoParamType, ())

def __copy__(self):

return NoParam

def __deepcopy__(self, memo):

return NoParam

def __call__(self, default):

pass

# Create the only instance of _NoParamType that should ever exist

# When the module is first loaded, globals() will not contain NoParam. A

# NameError will be thrown, causing the first instance of NoParam to be

# instanciated.

# If the module is reloaded (via imp.reload), globals() will contain

# NoParam. This skips the code that would instantiate a second object

# Note: it is possible to hack around this via

# >>> del util_const.NoParam

# >>> imp.reload(util_const)

try:

NoParam

except NameError:

NoParam = object.__new__(_NoParamType)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值