python赋值和拷贝

文章探讨了Python中赋值、浅拷贝和深拷贝的概念,以及它们如何影响内存地址和对象的可变性。在函数参数传递时,由于默认值的共享可能导致意外的副作用,文章提出应谨慎处理可变参数,如使用深拷贝防止影响原对象。同时,澄清了Python参数传递按值(实际是引用的副本)的机制,说明了为何可变对象在函数内部的修改会影响外部状态。
摘要由CSDN通过智能技术生成
赋值,值相同,内存地址相同–函数参数传递。浅拷贝,值相同,内存地址不同。

拷贝第一层内存地址的引用。第一层元素为可变元素。拷贝过的引用会跟着发生变化。否则不发生变化

import copy
a = [[], 'hello', 'world', {}]
b = a
c = copy.copy(a)
a
[[], 'hello', 'world', {}]
b
[[], 'hello', 'world', {}]
c
[[], 'hello', 'world', {}]
a[0].append('hi')
a.append('小明')
a
[['hi'], 'hello', 'world', {}, '小明']
b
[['hi'], 'hello', 'world', {}, '小明']
c
[['hi'], 'hello', 'world', {}]

浅拷贝只是拷贝第一层地址的引用。

函数参数传递–引用

class T:

    def __init__(self, passengers=[]):
        self.passengers = passengers

    def pick(self, v):
        self.passengers.append(v)

    def remove(self, v):
        self.passengers.remove(v)

        
t1 = T()
t1..pick('hi')
t2 = T()
t1.passengers
t2.passengers

# ['hi']
# ['hi']

出现问题的原因是:实例化对象时没有指定 passengers 实例会共享列表

问题根源:默认值在定义函数时计算(通常在加载模块时)__init__检查参数为None赋值一个列表。否则示例化时共享列表。

防御可变函数带来的影响

如果函数接受可变参数。应该谨慎考虑调用方法是否期望修改传入的参数。

例如:参数是一个字典,而且在处理的过程中需要修改它。那么,你要考虑!!!函数外部是否会收到影响

# passengers 避免受到影响

class Test:

    def __init__(self, passengers=None):
        if passengers is None:
            self.passengers = []
        else:
            # 深拷贝
            self.passengers = list(passengers)

    def pick(self, v):
        self.passengers.append(v)

    def remove(self, v):
        self.passengers.remove(v)
        
        
 def test(passengers=None):
    if passengers is None:
        passengers = []
    else:
        # 深拷贝
        passengers = copy.deepcopy(passengers)

函数传递的方式

人们经常说:参数按值传递,但是这里是值得引用。这么说没有错,但是会引起误解。因为,在旧式语言中,最常用的参数传递方式有根据值传递(函数得到参数的副本)和按照引用传递(函数得到参数的指针)。Python中函数得到参数的副本(可以理解为浅拷贝),但是参数始终是引用。因此,参数是一个可变对象,那么对象可能被修改,但是对象的标识(内存地址)不变。此外,因为函数得到的参数是引用的副本。所以重新绑定对函数的外部没有影响。

简单理解

def func(x=[[], 1]):
    print(x)
    x.append('a')
    print(x)
    x[0].append('b')
    print(x)
# func 参数时一个可变类型
func()
func()
# 第一次调用x=[['b'], 1, 'a']
# 此时在func(x=[['b'], 1, 'a']) 不在是 func(x=[[], 1])。有点类似 在函数外部定义的 x=[[], 1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>