Добро пожаловать в общедоступный номер: специалист по данным python
【Ключевые моменты, которые стоит увидеть в первую очередь】
1. Модификация изменяемых объектов на месте
2. Как получить независимую копию объекта
3. Сравнение, равенство и проблемы истинности
Наша сегодняшняя тема должна начаться с «модификации изменяемых объектов на месте», что является примечательной проблемой.
Как мы говорили в предыдущем эпизоде, операции присваивания всегда хранят ссылки на объекты, а не копии этих объектов. Поскольку операции присваивания в этом процессе будут генерировать несколько ссылок на один и тот же объект, нам нужно знать о возможных проблемах с «изменяемыми объектами» здесь:Изменение изменяемого объекта на месте может повлиять на другие переменные в программе, которые ссылаются на этот объект.Если вы не хотите видеть этот сценарий, вам нужно явно скопировать объект, а не просто назначать его.
X = [1,2,3,4,5]
L = ['a', X, 'b']
D = {'x':X, 'y':2}
print(L)
print(D)
['a', [1, 2, 3, 4, 5], 'b']
{'y': 2, 'x': [1, 2, 3, 4, 5]}
В этом примере мы видим, что список [1, 2, 3, 4, 5] имеет три ссылки, на которые ссылается переменная X, на которую ссылается элемент внутри списка L и на который ссылается элемент внутри словаря D.Затем использование любой из этих трех ссылок для изменения списка [1, 2, 3, 4, 5] также изменит объекты двух других ссылок., например, я использую L для изменения второго элемента [1, 2, 3, 4, 5], и результат операции очень очевиден.
X = [1,2,3,4,5]
L = ['a', X, 'b']
D = {'x':X, 'y':2}
L[1][2] = 'changed'
print(X)
print(L)
print(D)
[1, 2, 'changed', 4, 5]
['a', [1, 2, 'changed', 4, 5], 'b']
{'x': [1, 2, 'changed', 4, 5], 'y': 2}
[Сестра сказала] Пожалуйста, объезжайте, если есть ямы, в этих местах очень легко ошибиться.
Ссылки — это аналог указателей более высокого уровня в других языках. Это может помочь вам передавать большие объекты в любом месте области действия программы, не создавая копии по пути, и играть роль оптимизации программы.
[Сестра сказала] Но что, если я не хочу делиться ссылкой на объект, а хочу получить независимую копию объекта?
Можно подумать, что этот слой действительно хорош, на самом деле это очень просто, обычно используемые методы следующие:
Первый способ: выражение шардинга может вернуть новую копию объекта, а выражение неограниченного шардинга может полностью скопировать список
L = [1,2,3,4,5]
C = L[1:3]
C[0] = 8
print(C)
print(L)
[8, 3]
[1, 2, 3, 4, 5]
L = [1,2,3,4,5]
C = L[:]
C[0] = 8
print(C)
print(L)
[8, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
Видно, что с помощью выражения фрагментации получается новая копия списка C, и значение исходного списка L не изменится при модификации этого списка.
Второй метод: метод копирования словаря также может обеспечить полную копию словаря:
D = {'a':1, 'b':2}
B = D.copy()
B['a'] = 888
print(B)
print(D)
{'a': 888, 'b': 2}
{'a': 1, 'b': 2}
Третий тип: встроенный список функций может генерировать копию
L = [1,2,3,4]
C = list(L)
C[0] = 888
print(C)
print(L)
[888, 2, 3, 4]
[1, 2, 3, 4]
Наконец, давайте рассмотрим более сложный пример.
B получает копию списка A посредством операции неограниченной фрагментации. Модификация элементов в списке B не повлияет на A, например, изменение значения, например замена ссылки другой ссылкой на список:
L = [1,2,3,4]
A = [1,2,3,L]
B = A[:]
B[1] = 333
B[3] = ['888','999']
print(B)
print(A)
print(L)
[1, 333, 3, ['888', '999']]
[1, 2, 3, [1, 2, 3, 4]]
[1, 2, 3, 4]
Но что, если это сценарий?
L = [1,2,3,4]
A = [1,2,3,L]
B = A[:]
B[1] = 333
B[3][1] = ['changed']
print(B)
print(A)
print(L)
[1, 333, 3, [1, ['changed'], 3, 4]]
[1, 2, 3, [1, ['changed'], 3, 4]]
[1, ['changed'], 3, 4]
Поскольку последний элемент B также является ссылкой на список L (его можно рассматривать как получение адреса L), дальнейшая модификация содержащихся элементов объекта списка через эту ссылку также повлияет на сами A и L.
Поэтому операция неограниченной фрагментации и метод копирования словаря могут выполнять только присваивания верхнего уровня.На верхнем уровне, если это числовой объект, значение копируется, а если это ссылка на объект, ссылка копируется напрямую, поэтому на следующем уровне все еще существует скрытое явление общей ссылки.
Если вы хотите добиться полного и независимого нисходящего, глубокого копирования ссылок на каждом уровне, вы должны использовать метод deepcopy модуля копирования.
import copy
L = [1,2,3,4]
A = [1,2,3,L]
B = copy.deepcopy(A)
B[3][1] = ['changed']
print(B)
print(A)
print(L)
[1, 2, 3, [1, ['changed'], 3, 4]]
[1, 2, 3, [1, 2, 3, 4]]
[1, 2, 3, 4]
Таким образом реализуется рекурсивный обход объекта для копирования всех его компонентов, причем реализуется полная копия, между которыми нет связи.
[Сестра сказала] Ну, я действительно не ожидала, что в простом задании столько ям! Я резюмирую от себя: присваивание common = на самом деле является только общей ссылкой; три метода неограниченного сегментирования, метод копирования словаря и встроенный список функций могут копировать объект верхнего уровня, а глубокое копирование может полностью реализовать объект верхнего уровня. объект Полная копия вниз. Поэтому, когда мы на самом деле его используем, мы должны учитывать эти огромные различия!
Напоследок добавим небольшое знание: проблемы сравнения, равенства и истинности в python.
L1 = [1,2,['A','B']]
L2 = [1,2,['A','B']]
L3 = L1
print(L1 == L2, L1 is L2)
print(L1 == L3, L1 is L3)
True False
True True
== проверяет равенство двух значений объекта, то есть рекурсивно сравнивает все внедренные объекты;
проверяет непротиворечивость двух объектов, то есть находятся ли они в одном и том же пространстве памяти.
проблема истинности
Python рассматривает любую пустую структуру данных как ложную, а любую непустую структуру данных как истинную.
Использование None обычно играет роль пустого заполнителя, который является ложным, когда оценивается истинное значение.
L = [None] * 10
print(L)
[None, None, None, None, None, None, None, None, None, None]
Встроенная функция bool может проверить, является ли объект истинным или ложным.
print(bool([1,2]))
print(bool(True))
print(bool(None))
print(bool('abcde'))
True
True
False
True
QR-код официального аккаунта: специалист по данным python: