Python 中的冻结?
我已经用Python编程一段时间了,最近在工作中开始使用Ruby。这两种语言非常相似。不过,我刚遇到一个Ruby的特性,我不知道怎么在Python中实现,那就是Ruby的freeze
方法。
irb(main):001:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):002:0> a[1] = 'chicken'
=> "chicken"
irb(main):003:0> a.freeze
=> [1, "chicken", 3]
irb(main):004:0> a[1] = 'tuna'
TypeError: can't modify frozen array
from (irb):4:in `[]='
from (irb):4
有没有办法在Python中模仿这个功能呢?
补充说明:我意识到我让人觉得这个功能只适用于列表;其实在Ruby中,freeze
是一个在Object
上的方法,所以你可以让任何对象变得不可变。我为造成的混淆感到抱歉。
2 个回答
15
>>> a = [1,2,3]
>>> a[1] = 'chicken'
>>> a
[1, 'chicken', 3]
>>> a = tuple(a)
>>> a[1] = 'tuna'
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
a[1] = 'tuna'
TypeError: 'tuple' object does not support item assignment
另外,可以对比一下 set
和 frozenset
,还有 bytearray
和 bytes
。
数字和字符串本身是不可改变的:
>>> a = 4
>>> id(a)
505408920
>>> a = 42 # different object
>>> id(a)
505409528
13
你可以创建一个新的类,继承自 list
,然后添加一个叫做“frozen”的标志,这样就可以阻止 __setitem__
进行任何操作了:
class freezablelist(list):
def __init__(self,*args,**kwargs):
list.__init__(self, *args)
self.frozen = kwargs.get('frozen', False)
def __setitem__(self, i, y):
if self.frozen:
raise TypeError("can't modify frozen list")
return list.__setitem__(self, i, y)
def __setslice__(self, i, j, y):
if self.frozen:
raise TypeError("can't modify frozen list")
return list.__setslice__(self, i, j, y)
def freeze(self):
self.frozen = True
def thaw(self):
self.frozen = False
接下来可以试着使用它:
>>> from freeze import freezablelist as fl
>>> a = fl([1,2,3])
>>> a[1] = 'chicken'
>>> a.freeze()
>>> a[1] = 'tuna'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "freeze.py", line 10, in __setitem__
raise TypeError("can't modify frozen list")
TypeError: can't modify frozen list
>>> a[1:1] = 'tuna'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "freeze.py", line 16, in __setslice__
raise TypeError("can't modify frozen list")
TypeError: can't modify frozen list
>>>