Вопрос

Учти это код:

a = {...} # a is an dict with arbitrary contents
b = a.copy()
  1. Какую роль воспроизводится мультипликация в ключах и значениях диктовых?
  2. Как мне убедиться, что изменения к ключам или значениям одного дикта не отражены в другом?
  3. Как это относится к Hashable ограничение ключей Dict?
  4. Есть ли различия в поведении между Python 2.x и Python 3.x?

Как я могу проверить, является ли тип мультипликации в Python?

Это было полезно?

Решение

1) Ключи не должны быть измельчены, пока не У вас есть класс, определенный пользователем, который является Hashable, но и Metable. Это все, что вынуждено на вас. Однако, используя Hashable, Musicable объект в качестве ключа Dict, может быть плохой идеей.

2) не делясь ценностями между двумя дикторами. Одно делиться ключами, потому что они должны быть неизменными. Копирование словаря, в copy Смысл модуля, определенно безопасен. Звонить конструктор Dict здесь работает тоже: b = dict(a). Отказ Вы также можете использовать неизменные значения.

3) Все встроенные неизменные типы одновременно одновременно. Все встроенные мусорные типы не являются одновременными. Для того, чтобы объект был хмаривым, он должен иметь то же самое хеш в течение всего его жизни, даже если оно мутировано.

4) не то, что я знаю; Я описываю 2.x.

Тип смешен, если он не неизменно. Тип неизменен, если это встроенный неизменный тип: str, int, long, bool, float, tuple, и, вероятно, пара других я забываю. Пользовательские типы всегда мультируются.

Объект сметен, если он не неизменен. Объект неизменен, если оно состоит рекурсивно, только из неизменных введенных подразделений. Таким образом, кортеж списков сметен; Вы не можете заменить элементы кортежа, но вы можете изменять их через интерфейс списка, изменяя общие данные.

Другие советы

На самом деле нет никакой такой вещи, как мутуматамность или неизменность на уровне языка в Python. Некоторые объекты не имеют возможности изменить их (например, строки и кортежи), и так эффективно неизменно, но это чисто концептуально; На языковом уровне нет свойств, указывающих на это, ни к вашему коду, ни в себе Python.

Неизменность на самом деле не актуальна для диклиментов; Это совершенно нормально, чтобы использовать смежные значения в качестве клавиш. Что имеет значение сравнения и перемешивания: объект всегда должен оставаться равным себе. Например:

class example(object):
    def __init__(self, a):
        self.value = a
    def __eq__(self, rhs):
        return self.value == rhs.value
    def __hash__(self):
        return hash(self.value)

a = example(1)
d = {a: "first"}
a.data = 2
print d[example(1)]

Здесь, example является нет неизменный; Мы изменяем это с a.data = 2. Отказ Тем не менее, мы используем его как ключ от хеша без проблем. Почему? Имущество, которое мы меняемся, не влияет на равенство: хеш не изменился, а также example(1) всегда равен example(1), игнорируя любые другие свойства.

Наиболее распространенное использование этого является кэширование и воспоминание: наличие кэширования свойства или не логически не меняет объект, и обычно не влияет на равенство.

(Я собираюсь остановиться здесь - пожалуйста, не задавайте пять вопросов одновременно.)

Есть мутабсексуализм, запутанные, мутаблемые в модуле коллекции. Отказ Который может быть использован для проверки мулюбимости предшественников.

issubclass(TYPE, (MutableSequence, MutableSet, MutableMapping))

Если вы хотите использовать это на определенных пользователях пользователей, тип должен быть либо унаследован от одного из них, либо зарегистрирован как виртуальный подкласс.

class x(MutableSequence):
    ...

или

class x:
    ...

abc.ABCMeta.register(MutableSequence,x)

Там действительно нет гарантия что тип, который есть Hashable, также неизменно, но по крайней мере, правильно реализует __hash__ Требуется, чтобы тип неизменен, по отношению к своему хэш и равенству. Это не принудительно в любом случае.

Однако мы все взрослые. Было бы неразумно реализовать __hash__ Если вы действительно не имели в виду это. Грубо говоря, это просто сводится к тому, что если тип на самом деле можно использовать в качестве ключа словаря, то он предназначен для использования таким образом.

Если вы ищете то, что есть нравится Дикт, но и неизменный, то namedtuple Может быть, ваша лучшая ставка от того, что в стандартной библиотеке. По общему признанию, это не очень хорошее приближение, но это начало.

  1. обдумывать ключи должен быть усугубляется, что подразумевает, что у них есть неизменяемый хэш ценность. обдумывать ценности может или не может быть измененым; Однако, если они смены, это влияет на ваш второй вопрос.

  2. «Изменения к ключам» не будут отражены между двумя дикторами. Изменения в неизменных значениях, таких как строки, также не будут отражены. Изменения на смежных объектах, таких как пользовательские заданные классы будут отражены, поскольку объект сохраняется по ID (т. Е. Ссылка).

    class T(object):
      def __init__(self, v):
        self.v = v
    
    
    t1 = T(5)
    
    
    d1 = {'a': t1}
    d2 = d1.copy()
    
    
    d2['a'].v = 7
    d1['a'].v   # = 7
    
    
    d2['a'] = T(2)
    d2['a'].v   # = 2
    d1['a'].v   # = 7
    
    
    import copy
    d3 = copy.deepcopy(d2) # perform a "deep copy"
    d3['a'].v = 12
    d3['a'].v   # = 12
    d2['a'].v   # = 2
    
  3. Я думаю, что это объясняется первыми двумя ответами.

  4. Не то чтобы я знаю в этом отношении.

Некоторые дополнительные мысли:

Есть два главных вещей, которые нужно знать для понимания поведения ключи: ключи должны быть замашина (что означает, что они реализуют object.__hash__(self)) и они также должны быть «сопоставимыми» (что означает, что они реализуют что-то вроде object.__cmp__(self)). Одно важное убранное из документов: по умолчанию, определенные пользователем объекты хеш-функции возвращают id().

Рассмотрим этот пример:

class K(object):
  def __init__(self, x, y):
     self.x = x
     self.y = y
  def __hash__(self):
     return self.x + self.y

k1 = K(1, 2)
d1 = {k1: 3}
d1[k1] # outputs 3
k1.x = 5
d1[k1] # KeyError!  The key's hash has changed!
k2 = K(2, 1)
d1[k2] # KeyError!  The key's hash is right, but the keys aren't equal.
k1.x = 1
d1[k1] # outputs 3

class NewK(object):
  def __init__(self, x, y):
     self.x = x
     self.y = y
  def __hash__(self):
     return self.x + self.y
  def __cmp__(self, other):
     return self.x - other.x

nk1 = NewK(3, 4)
nd1 = {nk1: 5}
nd1[nk1] # outputs 5
nk2 = NewK(3, 7)
nk1 == nk2 # True!
nd1[nk2] # KeyError! The keys' hashes differ.
hash(nk1) == hash(nk2) # False
nk2.y = 4
nd1[nk2] # outputs 5

# Where this can cause issues:
nd1.keys()[0].x = 5
nd1[nk1] # KeyError! nk1 is no longer in the dict!
id(nd1.keys()[0]) == id(nk1)  # Yikes. True?!
nd1.keys()[0].x = 3
nd1[nk1]  # outputs 5
id(nd1.keys()[0]) == id(nk1)  # True!

Ценности Гораздо легче понимать, диктовые хранилищ ссылок на объекты. Прочитайте разделы на hashable. Такие, как строки неизменны, если вы «поменяете» их, Dict вы изменили его в настоящее время, ссылаются на новый объект. Объекты, которые являются смежными, могут быть «изменены на месте», следовательно, значение обоих диктопов изменятся.

d1 = {1: 'a'}
d2 = d1.copy()
id(d1[1]) == id(d2[1]) # True
d2[1] = 'z'
id(d1[1]) == id(d2[1]) # False

# the examples in section 2 above have more examples of this.

Во всяком случае, вот основные пункты всего этого:

  • За ключи, а может и не быть мультипликация, скорее Хаша и сопоставимость, что вы заботитесь о.
  • Вы заботитесь о мультиплизме для значений, поскольку по определению, значение смешанного объекта может быть изменено без изменения ссылки на него.

Я не думаю, что есть общий способ проверить любой из этих моментов. Тесты на пригодность будут зависеть от вашего использования. Например, может быть достаточно, чтобы проверить, что объект делает или не реализует __hash__ и сравнение (__eq__ или __cmp__) Функции. Как-мудрый, вы можете «проверить» объект __setattr__ Метод в некотором роде, чтобы определить, является ли оно смешно.

Диктовы являются неупорядоченные наборы ключей: ценности пар. Ключи должны быть неизменными, и, следовательно, hashable. Чтобы определить, является ли объект hashable, вы можете использовать hash() Функция:

>>> hash(1)
1
>>> hash('a')
12416037344
>>> hash([1,2,3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash((1,2,3))
2528502973977326415
>>> hash({1: 1})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

Значения, с другой стороны, могут быть любым объектом. Если вам нужно проверить, является ли объект неизменен, то я бы использовал hash().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top