Заморозить в Python? - PullRequest
       7

Заморозить в Python?

12 голосов
/ 15 октября 2010

Я некоторое время программировал на Python и совсем недавно начал использовать Ruby на работе. Языки очень похожи. Тем не менее, я только что натолкнулся на функцию Ruby, которую я не знаю, как копировать в Python. Это метод Руби 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 ]

12 голосов
/ 15 октября 2010
>>> 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
11 голосов
/ 15 октября 2010

Вы всегда можете создать подкласс list и добавить «замороженный» флаг, который будет блокировать __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
>>>
...