Ссылки на Python 2.7 dict - Как сделать ключ? [Дубликат]

Вот некоторые подходы к работе с асинхронными запросами:
  1. Объект обезьяны браузера
  2. Q - A
  3. A + Promises.js
  4. jQuery отложен
  5. API XMLHttpRequest
  6. Использование концепции обратного вызова - как реализация в первом ответе

Пример: jQuery отложенная реализация для работы с несколькими запросами

var App = App || {};

App = {
    getDataFromServer: function(){

      var self = this,
                 deferred = $.Deferred(),
                 requests = [];

      requests.push($.getJSON('request/ajax/url/1'));
      requests.push($.getJSON('request/ajax/url/2'));

      $.when.apply(jQuery, requests).done(function(xhrResponse) {
        return deferred.resolve(xhrResponse.result);
      });
      return deferred;
    },

    init: function(){

        this.getDataFromServer().done(_.bind(function(resp1, resp2) {

           // Do the operations which you wanted to do when you
           // get a response from Ajax, for example, log response.
        }, this));
    }
};
App.init();
473
задан poke 24 February 2014 в 14:25
поделиться

16 ответов

Это тоже смутило меня, потому что я исходил из фона C.

В C переменная - это место в памяти с определенным типом. Назначение переменной копирует данные в ячейку памяти переменной.

Но в Python переменные действуют скорее как указатели на объекты. Поэтому присвоение одной переменной другой не создает копию, она просто превращает это имя переменной в один и тот же объект.

6
ответ дан Craig McQueen 25 August 2018 в 10:14
поделиться

Вы также можете просто создать новый словарь с пониманием словаря. Это позволяет избежать импорта копии.

dout = dict((k,v) for k,v in mydict.items())

Конечно, в python> = 2.7 вы можете сделать:

dout = {k:v for k,v in mydict.items()}

Но для обратной совместимости лучший способ лучше.

32
ответ дан Dashing Adam Hughes 25 August 2018 в 10:14
поделиться

Лучший и самый простой способ создать копию dict в обоих Python 2.7 и 3 ...

Чтобы создать копию простого (одноуровневого ) словарь:

1. Используя метод dict (), вместо создания ссылки, которая указывает на существующий dict.

my_dict1 = dict()
my_dict1["message"] = "Hello Python"
print(my_dict1)  # {'message':'Hello Python'}

my_dict2 = dict(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

2. Использование встроенного метода update () для словаря python.

my_dict2 = dict()
my_dict2.update(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

Чтобы создать копию вложенного или сложного словаря:

Используйте встроенный модуль копирования, который обеспечивает общие операции мелкой и глубокой копии. Этот модуль присутствует как в Python 2.7, так и в 3. *

import copy

my_dict2 = copy.deepcopy(my_dict1)
6
ответ дан Emrit 25 August 2018 в 10:14
поделиться

Вы можете скопировать и отредактировать недавно созданную копию за один проход, вызвав конструктор dict с дополнительными аргументами ключевого слова:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}
9
ответ дан Frerich Raabe 25 August 2018 в 10:14
поделиться
>>> x={'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> u=x.copy()
>>> v=dict(x)
>>> import copy
>>> w=copy.deepcopy(x)
>>> x['a']=10
>>> x
{'a': 10, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> u
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> v
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> w
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> x['b']['m']=40
>>> x
{'a': 10, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> u
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> v
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> w
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
111
ответ дан gpanda 25 August 2018 в 10:14
поделиться

Когда вы назначаете dict2 = dict1, вы не делаете копию dict1, это приводит к тому, что dict2 является просто другим именем для dict1.

Чтобы скопировать изменяемые типы, такие как словари , используйте copy / deepcopy модуля copy .

import copy

dict2 = copy.deepcopy(dict1)
348
ответ дан Imran 25 August 2018 в 10:14
поделиться

Операторы присваивания в Python не копируют объекты, они создают привязки между объектом и объектом.

, поэтому, dict2 = dict1, он вызывает другое связывание между dict2 и объектом, к которому dict1 относится.

, если вы хотите скопировать dict, вы можете использовать copy module. Модуль копирования имеет два интерфейса:

copy.copy(x)
Return a shallow copy of x.

copy.deepcopy(x)
Return a deep copy of x.

Разница между мелким и глубоким копированием применима только для составных объектов (объектов, которые содержат другие объекты, например списки или экземпляры классов):

мелкая копия создает новый составной объект, а затем (по мере возможности) вставляет ссылки в него в объекты, найденные в оригинале.

A глубокая копия создает новый составной объект, а затем рекурсивно вставляет в него копии объектов, найденных в оригинале.

Например, в python 2.7.9:

>>> import copy
>>> a = [1,2,3,4,['a', 'b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> a[4].append('c')

, а результат:

>>> a
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> b
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> c
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, ['a', 'b']]
13
ответ дан loosen 25 August 2018 в 10:14
поделиться

Python never неявно копирует объекты. Когда вы устанавливаете dict2 = dict1, вы делаете их ссылкой на один и тот же точный объект dict, поэтому, когда вы его мутируете, все ссылки на него продолжают ссылаться на объект в его текущем состоянии.

Если вы хотите скопируйте dict (что редко), вы должны сделать это явно с помощью

dict2 = dict(dict1)

или

dict2 = dict1.copy()
556
ответ дан Mike Graham 25 August 2018 в 10:14
поделиться

В python 3.5+ есть более простой способ получить мелкую копию с помощью оператора ** распаковки. Определено Pep 448 .

>>>dict1 = {"key1": "value1", "key2": "value2"}
>>>dict2 = {**dict1}
>>>print(dict2)
{'key1': 'value1', 'key2': 'value2'}
>>>dict2["key2"] = "WHY?!"
>>>print(dict1)
{'key1': 'value1', 'key2': 'value2'}
>>>print(dict2)
{'key1': 'value1', 'key2': 'WHY?!'}

** распаковывает словарь в новый словарь, который затем присваивается dict2.

Мы также можем подтвердить, что каждый словарь имеет отдельный идентификатор.

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

Если требуется глубокая копия, то copy.deepcopy () все еще остается в пути.

37
ответ дан PabTorre 25 August 2018 в 10:14
поделиться

Как объяснили другие, встроенный dict не делает то, что вы хотите. Но в Python2 (и, вероятно, 3 тоже) вы можете легко создать класс ValueDict, который копирует с помощью =, чтобы вы могли быть уверены, что оригинал не изменится.

class ValueDict(dict):

    def __ilshift__(self, args):
        result = ValueDict(self)
        if isinstance(args, dict):
            dict.update(result, args)
        else:
            dict.__setitem__(result, *args)
        return result # Pythonic LVALUE modification

    def __irshift__(self, args):
        result = ValueDict(self)
        dict.__delitem__(result, args)
        return result # Pythonic LVALUE modification

    def __setitem__(self, k, v):
        raise AttributeError, \
            "Use \"value_dict<<='%s', ...\" instead of \"d[%s] = ...\"" % (k,k)

    def __delitem__(self, k):
        raise AttributeError, \
            "Use \"value_dict>>='%s'\" instead of \"del d[%s]" % (k,k)

    def update(self, d2):
        raise AttributeError, \
            "Use \"value_dict<<=dict2\" instead of \"value_dict.update(dict2)\""


# test
d = ValueDict()

d <<='apples', 5
d <<='pears', 8
print "d =", d

e = d
e <<='bananas', 1
print "e =", e
print "d =", d

d >>='pears'
print "d =", d
d <<={'blueberries': 2, 'watermelons': 315}
print "d =", d
print "e =", e
print "e['bananas'] =", e['bananas']


# result
d = {'apples': 5, 'pears': 8}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
d = {'apples': 5, 'pears': 8}
d = {'apples': 5}
d = {'watermelons': 315, 'blueberries': 2, 'apples': 5}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
e['bananas'] = 1

# e[0]=3
# would give:
# AttributeError: Use "value_dict<<='0', ..." instead of "d[0] = ..."

Пожалуйста, обратитесь к шаблон изменения lvalue, обсуждаемый здесь: Python 2.7 - чистый синтаксис для модификации lvalue . Главное наблюдение заключается в том, что str и int ведут себя как значения в Python (даже если они фактически являются неизменяемыми объектами под капотом). В то время как вы это замечаете, также обратите внимание, что ничего особенного в str или int нет. dict можно использовать почти одинаково, и я могу думать о многих случаях, когда ValueDict имеет смысл.

1
ответ дан personal_cloud 25 August 2018 в 10:14
поделиться

dict1 - это символ, который ссылается на базовый объект словаря. Назначение dict1 - dict2 просто присваивает ту же ссылку. Изменение значения ключа с помощью символа dict2 изменяет базовый объект, что также влияет на dict1. Это запутанно.

Гораздо проще рассуждать о неизменяемых значениях, чем ссылки, поэтому по возможности делайте копии:

person = {'name': 'Mary', 'age': 25}
one_year_later = {**person, 'age': 26}  # does not mutate person dict

Это синтаксически то же самое, что:

one_year_later = dict(person, age=26)
5
ответ дан Petrus Theron 25 August 2018 в 10:14
поделиться

Поскольку python работает со ссылкой, поэтому, когда вы сделали dict2 = dict1, вы передаете ссылку на dict2, это было то же самое, что и dict1. Итак, когда вы вносите изменения в dict1 или dict2, вы меняете ссылку, и оба определяют chages. Извините, если я что-то ошибся на английском.

1
ответ дан Rodrigo Moraes 25 August 2018 в 10:14
поделиться

dict2 = dict1 не копирует словарь. Это просто дает программисту второй способ (dict2) ссылаться на тот же словарь.

6
ответ дан user 25 August 2018 в 10:14
поделиться

Вы можете использовать напрямую:

dict2 = eval(repr(dict1))

, где объект dict2 является независимой копией dict1, поэтому вы можете изменить dict2 без влияния на dict1.

Это работает для любого типа объект. [/ д2]

-4
ответ дан Viiik 25 August 2018 в 10:14
поделиться

, потому что, dict2 = dict1, dict2 содержит ссылку на dict1. Оба dict1 и dict2 указывают на то же место в памяти. Это обычный случай при работе с изменяемыми объектами в python. Когда вы работаете с изменяемыми объектами в python, вы должны быть осторожны, поскольку его трудно отлаживать. Например, в следующем примере.

 my_users = {
        'ids':[1,2],
        'blocked_ids':[5,6,7]
 }
 ids = my_users.get('ids')
 ids.extend(my_users.get('blocked_ids')) #all_ids
 print ids#output:[1, 2, 5, 6, 7]
 print my_users #output:{'blocked_ids': [5, 6, 7], 'ids': [1, 2, 5, 6, 7]}

Это примерное намерение состоит в том, чтобы получить все идентификаторы пользователей, включая заблокированные идентификаторы. То, что мы получили от переменной ids, но также непреднамеренно обновили значение my_users . когда вы расширили ids с помощью заблокированных_id , мои пользователи обновились, потому что ids относятся к my_users .

0
ответ дан Vkreddy Komatireddy 25 August 2018 в 10:14
поделиться

Каждая переменная в python (например, как dict1 или str или __builtins__ является указателем на некоторый скрытый платонический «объект» внутри машины.

Если вы установите dict1 = dict2, вы просто укажите dict1 на тот же объект (или местоположение памяти или любую другую аналогию, которая вам нравится), как dict2. Теперь объект, на который ссылается dict1, является тем же объектом, на который ссылается dict2.

Вы можете проверить: dict1 is dict2 должен быть True. Кроме того, id(dict1) должен быть таким же, как id(dict2).

Вы хотите dict1 = copy(dict2) или dict1 = deepcopy(dict2).

Разница между copy и deepcopy? deepcopy гарантирует, что элементы dict2 (вы указали его в списке?) также являются копиями.

't использовать deepcopy много - это, как правило, плохая практика писать код, который ему нужен (на мой взгляд).

7
ответ дан wisty 25 August 2018 в 10:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: