Python赋值/浅/深拷贝

一、可变对象和不可变对象

  • 可变对象,该对象所指向的内存中的值可以被改变。变量(准确的说是引用)改变后,实际上是其所指的值直接发生改变,并没有发生复制行为,也没有开辟新的出地址,通俗点说就是原地改变。比如列表list字典dict集合set
  • 不可变对象,该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。比如数值类型(int和float)字符串str元组tuple

二、赋值、浅拷贝、深拷贝

1. 赋值

1.1可变对象

a=b=obj 两者在内存中地址一致,并且子元素在内存的地址也一致,所以修改其中一个对象的值,另外一个对象的值肯定也会修改。

1.2 不可变对象

1.2.1 在缓存范围内

只要是某个定值(整型、浮点型、或者字符串),复制给任何对象,所指向的内存地址都是一致的。

1.2.2 不在缓存范围内

某个定值超过缓存范围,比如字符串过长、整型过大,会出现指向该定值的两个对象的内存地址不一致的情况。

2. 浅拷贝

  • 使用copy()函数 from copy import copy
  • 使用切片操作
  • 使用工厂函数(如list/dir/set)

2.1 可变对象

a=copy(b) a和b的内存地址不一致,但是子元素的内存地址都一致。如果b的子元素为不可变对象,那么修改任何一个对象中的该子元素,不会引起另一个对象的该子元素的改变;如果b的子元素为可变对象,那么修改任何一个对象中的该子元素,则会引起另一个对象相应的改变。(其实对子元素的修改就相当于赋值)。

2.2 不可变对象

相当于赋值。

3. 深拷贝

  • from copy import deepcopy

3.1 可变对象

a=deepcopy(b) a和b的内存地址不一致。如果子元素为不可变对象,那么深拷贝后内存地址也不一致,所以修改不会相互影响 ;如果子元素为可变对象,那么深拷贝后内存地址是一致的,但是修改也不会相互影响,具体参考不可变对象的赋值。

3.2 不可变对象

相当于赋值。

三、参考

Python命令行参数解析

一.getopt

import sys, getopt

opts, args = getopt.getopt(sys.argv[1:], '-a:', ['bb', 'dd='])
# 第一个参数一般为sys.argv[1:],这是因为argv[0]为脚本的路径;
# 第二个参数为短命令行参数;
# 第三个参数为长命令行参数;
for opt_name, opt_val in opts:
    print(opt_name, ':', opt_val)

目前遇到两个坑:短参数不能缺少;参数不止一个字母时,必须使用长参数。

二.argparse

import argparse

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="show example")
    parser.add_argument("-a", "--param_a", help="help of param_a", required=True)  # a参数必须给出
    parser.add_argument("-b", "--param_b", help="help of param_b", default=1, type=int,
                        choices=[0, 1])  # 默认值为1,取值范围为0和1
    exptypegroup = parser.add_mutually_exclusive_group()  # 表示下面参数r和l为互斥
    exptypegroup.add_argument("-r", help="remote mode")
    exptypegroup.add_argument("-l", "--local", help="local mode")
    ARGS = parser.parse_args()
    print(ARGS.param_a)  # 如果有长参数必须用长参数取值,ARGS.a会提示a不存在;除非只有短参数,比如r参数
    print(ARGS.param_b)
    print(ARGS.r)

Python命令行参数解析:getopt和argparse

python 参数模块 getopt 与 argparse