
发表日期: 2021-04-26 13:29:32 浏览次数:125
灵宝400电话办理【灵宝网站公司】灵宝百度优化、灵宝域名注册、灵宝网店美工、灵宝微信公众号托管
灵宝市位于豫秦晋三省交界处的河南省西部,南依秦岭,北濒黄河。辖10镇5乡,440个行政村,总面积3011平方公里,常住人口73.51万(2017年),其中:耕地面积84.7万亩,非农业人口11万。被誉为“黄金之城”、“苹果之乡”、“道家之源”、“旅游观光胜地”。 [1]
灵宝市地处黄河中游,是人类最早活动和发祥地之一。且位于古代长安、洛阳两大古都之间,古墓葬、古遗址遗存丰富。解放后,相继出土了两万多件珍贵文物,有近百件文物属全国罕见。 [2] 2017年12月,当选中国工业百强县(市)。 [3] 2018年10月,入选2018年度全国投资潜力百强县市。 [4] 2018年11月,入选2018年工业百强县(市)。 [5] 第二批国家农产品质量安全县。 [6]
2018年,完成地区生产总值完成534.3亿元,增长5.9%;一般公共预算收入完成21.1亿元;规上工业增加值完成53.1亿元,增长6%;固定资产投资完成240.3亿元,增长10%;社会消费品零售总额完成185.8亿元,增长10.6%;城镇和农村居民人均可支配收入分别增长8.2%、9.1%。 [7]
Python是一种动态类型编程语言,与C/C++等静态类型编程语言不同,Python中的变量没有固定的类型,变量也无需提前声明分配内存空间,因此我们可以给任何变量赋值任何符合Python规范的类型值,比如
交互式Python代码:
>>> var = 88 >>> var = 'hello world'
在C语言中,变量使用前需要提前声明并明确其类型(或声明和赋值可同一条语句执行),以便为其分配内存空间,比如
C代码:
int a; a = 100;
但在C语言中一般不可直接将其他类型值赋值给不同类型的变量(可强制类型转换的除外),例如如下代码就会报错:
C代码:
int a; a = "hello world";
在Python中将字面量或变量对另一个变量进行赋值可以理解为:给内存中的变量实体贴上一个标签。这个标签就是变量标识符。
交互式Python代码:
>>> a = 100 >>> b = a >>> a is b True
上述代码表明变量a与变量b是同一个对象,标识符a和标识符b都是内存中变量实体100的一个标签。在C语言中,因为每个变量都有自己的内存空间,变量赋值是将值复制到指定的内存中,因此进行赋值的两个变量只是值相同,但并不表示同一个对象。
C代码:
#include <stdio.h>
int a = 100;
int b;
b = a;
if (&a == &b)
{
printf("yse\n");
}
else
{
printf("no\n");
}
// 输出:noPython中函数的实参和形参之间以及返回值也是进行赋值操作的。
交互式Python代码:
>>> a = 3
>>> b = 5
>>> def func(m, n):
print(m is a)
print(n is b)
r = m + n
print('id(r):', id(r))
return r
>>> c = func(a, b)
True
True
id(r): 10914624
>>> id(c)
10914624根据上述代码可知,Python函数调用时形参会被实参进行赋值操作,即在执行c = func(a, b)时其实相当于在函数内部执行了m = a和n = b。那么就会出现一个问题,当实参为可变对象时,在函数内部就存在改变实参的风险。
交互式Python代码:
>>> a = [1, 2] >>> def func(List): List.append(a[0] + a[1]) return List >>> c = func(a) >>> print(c) [1, 2, 3] >>> print(a) [1, 2, 3] >>> id(a) == id(c) True
上述代码中a为列表类型(可变对象),在函数内部List添加了一个元素并返回。a,List和函数返回后的c表示同一个对象,这是我们之前讨论过的。现在我们讨论的重点是在函数内部改变了函数的实参,当然在有些情况下,我们正是需要借助这种特性完成某种功能,这种情况我们暂且不讨论。但在实际的工作中,更多的情况是我们不想函数更改实参,针对这种情况我们应该怎样规避实参被更改的风险呢?有三种方法:
下面我就来讨论今天的第二个重点:拷贝。
尽量使用不可变类型作实参
当实参为不可变对象时,函数内部形参的操作不会影响实参。
交互式Python代码:
>>> a = 55
>>> id(a)
10916224
>>> def func(value):
print('id(value):', id(value), 'value: ', value)
print(value is a)
value = 99
print('id(value):', id(value), 'value:', value)
print(value is a)
>>> func(a)
id(value): 10916224 value: 55
True
id(value): 10917632 value: 99
False
>>> print('id(a):', id(a), 'a:', a)
id(a): 10916224 a: 55上述代码中a为int类型(不可变类型),作为实参赋值给形参value,函数在执行value = 99之前value与a表示同一个对象,在执行之后value与a表示不同的对象,其实这很好理解就像我们前面讨论的,在执行赋值语句之后value标识符被“贴”到另一个内存变量实体99上了。
使用拷贝
以上两种都不想用?那就写代码的时候多注意吧
Python中的拷贝分为浅拷贝和深拷贝
浅拷贝
Python中的默认拷贝都是浅拷贝,这里我们就拿列表类型举个栗子,先看看列表有哪些拷贝方法,此处参考Python语言及其应用:
交互式Python代码:
>>> a = [1, 2, 3] >>> b = a.copy() >>> a [1, 2, 3] >>> b [1, 2, 3] >>> b is a False >>> c = list(a) >>> c [1, 2, 3] >>> c is a False >>> d = a[:] >>> d is a False
上述代码中显示出三种列表拷贝方法:
我们也可看到拷贝出来的对象与被拷贝对象不再是同一个对象,这也是拷贝的根本目的。当使用可变对象的拷贝进行函数传参可以避免函数内部修改实参。
交互式Python代码:
>>> a = [1, 2, 3] >>> def func(List): List.append(100) List[0] = 'hello' return List >>> b = func(a.copy()) >>> b ['hello', 2, 3, 100] >>> a [1, 2, 3]
好像一切都很完美,达到了我们的目的。于是我们编写了下面这样的代码:
交互式Python代码:
>>> a = [1, 'hello', 'world', [88, 99], 22]
>>> def func(List):
List.append('shawn')
List[0] = 'simon'
List[3][0] = 100
return List
>>> b = func(a.copy())
>>> b
['simon', 'hello', 'world', [100, 99], 22, 'shawn']
>>> a
[1, 'hello', 'world', [100, 99], 22]有瑕疵啊,这运行结果和我们想象的不一样,我们想象着变量a索引为3的元素值仍为[88, 99],但输出并不是这样,问题出在了哪里?原因在于我们前面所说的Python中的默认拷贝均为浅拷贝,如果我们想要输出达到我们的预期,则需要深拷贝。
使用列表对象的.copy()方法
使用list()转换函数
使用列表分片[:]
深拷贝
深拷贝就是在每个层次都对可变对象进行拷贝,浅拷贝只对最外层可变对象进行拷贝。
我们先来看看赋值的情况即b = a,如下图所示:
示意图a与b指向同一个对象,我们通过代码验证其正确性:
交互式Python代码:
>>> a = [1, 2, [3, 4]] >>> b = a >>> id(b) == id(a) True >>> id(a[0]) == id(b[0]) True >>> id(a[1]) == id(b[1]) True >>> id(a[2]) == id(b[2]) True >>> id(a[2][0]) == id(b[2][0]) True >>> id(a[2][1]) == id(b[2][1]) True
再来看看浅拷贝的情况,先上图:
上图中为b = a[:]示意图,b为a的浅拷贝,浅拷贝会将最外层可变对象进行拷贝,下面进行代码验证:
交互式Python代码:
>>> a = [1, 2, [3, 4]] >>> b = a[:] >>> id(b) == id(a) False >>> id(a[0]) == id(b[0]) True >>> id(a[1]) == id(b[1]) True >>> id(a[2]) == id(b[2]) True >>> id(a[2][0]) == id(b[2][0]) True >>> id(a[2][1]) == id(b[2][1]) True
最后来看看深拷贝,深拷贝我们需要用到copy库的deepcopy,示意图如下: 接下来进行代码验证:
交互式Python代码:
>>> from copy import deepcopy >>> >>> a = [1, 2, [3, 4]] >>> b = deepcopy(a) >>> id(a) == id(b) False >>> id(a[0]) == id(b[0]) True >>> id(a[1]) == id(b[1]) True >>> id(a[2]) == id(b[2]) False >>> id(a[2][0]) == id(b[2][0]) True >>> id(a[2][1]) == id(b[2][1]) True
因此当实参为可变对象且其中含有多层嵌套的可变对象时,如果我们不想因为我们的粗心让函数更改实参,那么我们就应该使用深拷贝,看代码:
交互式Python代码:
>>> a = [1, 2, [3, 4]]
>>> def func(List):
List.append('hello world')
List[0] = 'shawn'
List[2][0] = 'simon'
List[2][1] = 199
return List
>>> from copy import deepcopy
>>> b = func(deepcopy(a))
>>> a
[1, 2, [3, 4]]
>>> b
['shawn', 2, ['simon', 199], 'hello world']Note: Python中的深拷贝和浅拷贝只是针对可变对象而言,而对于不可变对象无所谓深拷贝还是浅拷贝,因为对于不可变对象两种拷贝和变量之间赋值没什么两样。
交互式Python代码:
>>> from copy import deepcopy >>> >>> a = 'hello world' >>> b = deepcopy(a) >>> c = a >>> id(a) == id(b) == id(c) True
Python中变量之间的赋值,相当于给变量多贴了一个“标签”,或者说给变量起了个别名
深拷贝、浅拷贝是针对可变对象说的,不可变对象无所谓什么拷贝
对于可变对象,深拷贝对每层可变对象都进行拷贝,而浅拷贝只对最外层进行拷贝
当函数实参为可变对象且我们不想函数改变实参本身,应尽量使用深拷贝,尤其在实参中嵌套了可变对象时

服务热线
顶部
备案号: 苏ICP备11067224号
CopyRight © 2011 书生商友信息科技 All Right Reserved
24小时服务热线:400-111-6878 E-MAIL:1120768800@qq.com QQ:1120768800
网址: http://www.768800.com 网站建设:上往建站
关键词: 网站建设| 域名邮箱| 服务器空间| 网站推广| 上往建站| 网站制作| 网站设计| 域名注册| 网络营销| 网站维护|
企业邮箱| 虚拟主机| 网络建站| 网站服务| 网页设计| 网店美工设计| 网站定制| 企业建站| 网站设计制作| 网页制作公司|
400电话办理| 书生商友软件| 葬花网| 调温纤维| 海洋馆运营维护| 北京保安公司| 殡仪馆服务| 殡葬服务| 苏州殡葬一条龙| 朝阳殡葬| 苏州殡葬服务|
欢迎您免费咨询,请填写以下信息,我们收到后会尽快与您联系
服务热线:400-111-6878