Этот ответ здесь, чтобы объяснить это поведение любому, кто разочарован результатами, которые им пытаются попытаться создать экземпляр dict
с fromkeys()
с изменяемым значением по умолчанию в этом dict
.
Рассмотрим :
#Python 3.4.3 (default, Nov 17 2016, 01:08:31)
# start by validating that different variables pointing to an
# empty mutable are indeed different references.
>>> l1 = []
>>> l2 = []
>>> id(l1)
140150323815176
>>> id(l2)
140150324024968
, поэтому любое изменение на l1
не повлияет на l2
и наоборот. это было бы верно для любого измененного до сих пор, включая dict
.
# create a new dict from an iterable of keys
>>> dict1 = dict.fromkeys(['a', 'b', 'c'], [])
>>> dict1
{'c': [], 'b': [], 'a': []}
это может быть удобной функцией. здесь мы присваиваем каждому ключу значение по умолчанию, которое также является пустым списком.
# the dict has its own id.
>>> id(dict1)
140150327601160
# but look at the ids of the values.
>>> id(dict1['a'])
140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328
Действительно, все они используют один и тот же ref! Изменение для одного - это изменение для всех, поскольку они на самом деле являются одним и тем же объектом!
>>> dict1['a'].append('apples')
>>> dict1
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
>>> id(dict1['a'])
>>> 140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328
для многих, это было не то, что было предназначено!
Теперь давайте попробуем это с явной копией списка, используемого в качестве значения по умолчанию.
>>> empty_list = []
>>> id(empty_list)
140150324169864
и теперь создаем dict с копией empty_list
.
>>> dict2 = dict.fromkeys(['a', 'b', 'c'], empty_list[:])
>>> id(dict2)
140150323831432
>>> id(dict2['a'])
140150327184328
>>> id(dict2['b'])
140150327184328
>>> id(dict2['c'])
140150327184328
>>> dict2['a'].append('apples')
>>> dict2
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
Still нет радости! Я слышал, как кто-то кричал, потому что я использовал пустой список!
>>> not_empty_list = [0]
>>> dict3 = dict.fromkeys(['a', 'b', 'c'], not_empty_list[:])
>>> dict3
{'c': [0], 'b': [0], 'a': [0]}
>>> dict3['a'].append('apples')
>>> dict3
{'c': [0, 'apples'], 'b': [0, 'apples'], 'a': [0, 'apples']}
По умолчанию fromkeys()
по умолчанию назначается значение None
.
>>> dict4 = dict.fromkeys(['a', 'b', 'c'])
>>> dict4
{'c': None, 'b': None, 'a': None}
>>> id(dict4['a'])
9901984
>>> id(dict4['b'])
9901984
>>> id(dict4['c'])
9901984
Действительно, все значения одинаковы (и единственные!) None
. Теперь, давайте повторим один из множества способов, через dict
и изменим значение.
>>> for k, _ in dict4.items():
... dict4[k] = []
>>> dict4
{'c': [], 'b': [], 'a': []}
Хмм. Выглядит так же, как и раньше!
>>> id(dict4['a'])
140150318876488
>>> id(dict4['b'])
140150324122824
>>> id(dict4['c'])
140150294277576
>>> dict4['a'].append('apples')
>>> dict4
>>> {'c': [], 'b': [], 'a': ['apples']}
Но они действительно отличаются []
s, что в данном случае было предполагаемым результатом.
Потому что по умолчанию используются значения по умолчанию.
Ниже приведен пример. поместите его после
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider"
connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</membership>
Поставщик членства по умолчанию настроен в вашем machine.config. Либо измените настройки в web.config, либо скопируйте настройки из вашего machine.config в свой web.config, чтобы настроить его. Возможно, вам потребуется добавить элемент
в веб-конфигурацию перед повторным добавлением.