如何在Python中创建具有高度限制实例的类
在Python中,有一些内置的类,它们的实例数量非常有限。比如,“None”是它所属类的唯一实例,而在布尔类中,只有两个对象,“True”和“False”(我希望我说的基本正确)。
另一个好的例子是整数:如果a和b都是int类型的实例,那么a == b就意味着a和b其实是同一个东西。
这里有两个问题:
怎么创建一个实例数量有限的类呢?比如,我们可以想要一个恰好有5个实例的类。或者像int类型那样,可以有无穷多个实例,但这些实例不是随便的。
如果整数形成一个类,为什么int()会返回0这个实例?这和一个用户自定义的类Cl相比,Cl()会返回这个类的一个实例,而不是一个特定的唯一实例,像0那样。难道int()不应该返回一个未指定的整数对象,也就是一个没有具体值的整数吗?
7 个回答
对于第一个问题,你可以使用单例模式来设计一个类,这种模式可以限制类的实例数量。你可以了解更多关于单例模式的信息,参考这个链接:http://en.wikipedia.org/wiki/Singleton_pattern。
对于第二个问题,我觉得这个链接可以帮助你理解你的问题:http://docs.python.org/library/stdtypes.html。
因为整数是有类型的,所以它们是有一些限制的。
这里还有一个资源可以参考... http://docs.python.org/library/functions.html#built-in-funcs
看起来第一个问题已经有很好的回答了,我想解释一个跟第二个问题有关的原则,这个原则似乎被所有回答者忽略了:对于大多数内置类型,当你不传参数调用这个类型时(也就是“默认构造函数”),它会返回一个该类型的实例,这个实例的值被认为是假的。也就是说,对于容器类型,它会返回一个空的容器;对于数字类型,它会返回一个等于零的数字。
>>> import decimal
>>> decimal.Decimal()
Decimal("0")
>>> set()
set([])
>>> float()
0.0
>>> tuple()
()
>>> dict()
{}
>>> list()
[]
>>> str()
''
>>> bool()
False
明白了吗?确实很常见!而且,对于可变类型,比如大多数容器,每次调用这个类型都会返回一个新的实例;而对于不可变类型,比如数字和字符串,情况就不一样了(可能会有内部优化,返回一个现有不可变实例的新引用,但这并不是必须的,若有这样的优化,通常会很有选择性地进行)。因为不可变类型的实例不能用 is
或者 id()
来比较。
如果你设计了一种类型,其中某些实例的值可以被认为是假的(通过在类中定义 __len__
或 __nonzero__
特殊方法),那么建议你遵循同样的原则(如果调用 __init__
[或者对于不可变类型的 __new__
] 时不带参数 [[当然除了 self
对于 __init__
和 'cls' 对于 __new__
]],就准备一个[[新的,如果是可变的]]“空”或“零值”实例)。
你提到的是给一个类赋予值语义,这通常是通过正常的方式创建类的实例来实现的,但要记住每一个实例。如果要创建一个匹配的实例,就返回已经创建的那个实例。在Python中,可以通过重载类的__new__
方法来实现这一点。
举个简单的例子,假设我们想用一对整数来表示坐标,并且希望有正确的值语义。
class point(object):
memo = {}
def __new__(cls, x, y):
if (x, y) in cls.memo: # if it already exists,
return cls.memo[(x, y)] # return the existing instance
else: # otherwise,
newPoint = object.__new__(cls) # create it,
newPoint.x = x # initialize it, as you would in __init__
newPoint.y = y
cls.memo[(x, y)] = newPoint # memoize it,
return newPoint # and return it!