- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python基础之变量的相关知识总结由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
跟其他编程语言不同,Python的变量不是盒子,不会存储数据,它们只是引用,就像标签一样,贴在对象上面.
比如:
1
2
3
4
5
6
7
|
>>> a
=
[
1
,
2
,
3
]
>>> b
=
a
>>> a.append(
4
)
>>> b
[
1
,
2
,
3
,
4
]
>>> b
is
a
True
|
a变量和b变量引用的是同一个列表[1, 2, 3]。b可以叫做a的别名.
比较来看:
1
2
3
4
5
6
|
>>> a
=
[
1
,
2
,
3
]
>>> c
=
[
1
,
2
,
3
]
>>> c
=
=
a
True
>>> c
is
a
False
|
c引用的是另外一个列表,虽然和a引用的列表的值相等,但是它们是不同的对象.
浅复制是指只复制最外层容器,副本中的元素是源容器中元素的引用。如果所有元素都是不可变的,那么这样没有问题,还能节省内容。但是,如果有可变的元素,那么结果可能会出乎意料之外。构造方法或[:]做的都是浅复制.
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
>>> x1
=
[
3
, [
66
,
55
,
44
], (
7
,
8
,
9
)]
# x2是x1的浅复制
>>> x2
=
list
(x1)
# 不可变元素没有影响
>>> x1.append(
100
)
>>> x1
[
3
, [
66
,
55
,
44
], (
7
,
8
,
9
),
100
]
>>> x2
[
3
, [
66
,
55
,
44
], (
7
,
8
,
9
)]
# x1[1]是列表,可变元素会影响x2
# 因为它们引用的是同一个对象
>>> x1[
1
].remove(
55
)
>>> x1
[
3
, [
66
,
44
], (
7
,
8
,
9
),
100
]
>>> x2
[
3
, [
66
,
44
], (
7
,
8
,
9
)]
# x2[1]也会反过来影响x1
>>> x2[
1
]
+
=
[
33
,
22
]
>>> x1
[
3
, [
66
,
44
,
33
,
22
], (
7
,
8
,
9
),
100
]
>>> x2
[
3
, [
66
,
44
,
33
,
22
], (
7
,
8
,
9
)]
# 不可变元组也不会有影响
# +=运算符创建了一个新元组
>>> x2[
2
]
+
=
(
10
,
11
)
>>> x1
[
3
, [
66
,
44
,
33
,
22
], (
7
,
8
,
9
),
100
]
>>> x2
[
3
, [
66
,
44
,
33
,
22
], (
7
,
8
,
9
,
10
,
11
)]
|
深复制是指我们常规理解的复制,副本不共享内部对象的引用,是完全独立的一个副本。这可以借助copy.deepcopy来实现.
示例:
1
2
3
4
5
6
7
8
9
|
>>> a
=
[
10
,
20
]
>>> b
=
[a,
30
]
>>> a.append(b)
>>> a
[
10
,
20
, [[...],
30
]]
>>>
from
copy
import
deepcopy
>>> c
=
deepcopy(a)
>>> c
[
10
,
20
, [[...],
30
]]
|
即使是有循环引用也能正确复制.
注意copy.copy()是浅复制,copy.deepcopy()是深复制.
Python唯一支持的参数传递模式是共享传参,也就是指函数的各个形式参数获得实参中各个引用的副本。因为Python的变量全都是引用。对于不可变对象来说没有问题,但是对于可变对象就不一样了.
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
>>>
def
f(a, b):
... a
+
=
b
...
return
a
...
# 数字不变
>>> x
=
1
>>> y
=
2
>>> f(x, y)
3
>>> x, y
(
1
,
2
)
# 列表变了
>>> a
=
[
1
,
2
]
>>> b
=
[
3
,
4
]
>>> f(a, b)
[
1
,
2
,
3
,
4
]
>>> a, b
([
1
,
2
,
3
,
4
], [
3
,
4
])
# 元组不变
>>> t
=
(
10
,
20
)
>>> u
=
(
30
,
40
)
>>> f(t, u)
(
10
,
20
,
30
,
40
)
>>> t, u
((
10
,
20
), (
30
,
40
))
|
由此可以得出一条警示:函数参数尽量不要使用可变参数,如果非用不可,应该考虑在函数内部进行复制.
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class
TwilightBus:
"""A bus model that makes passengers vanish"""
def
__init__(
self
, passengers
=
None
):
if
passengers
is
None
:
self
.passengers
=
[]
else
:
self
.passengers
=
passengers
def
pick(
self
, name):
self
.passengers.append(name)
def
drop(
self
, name):
self
.passengers.remove(name)
|
测试一下:
1
2
3
4
5
6
|
>>> basketball_team
=
[
'Sue'
,
'Tina'
,
'Maya'
,
'Diana'
,
'Pat'
]
>>> bus
=
TwilightBus(basketball_team)
>>> bus.drop(
'Tina'
)
>>> bus.drop(
'Pat'
)
>>> basketball_team
[
'Sue'
,
'Maya'
,
'Diana'
]
|
TwilightBus下车的学生,竟然从basketball_team中消失了。这是因为self.passengers引用的是同一个列表对象。修改方法很简单,复制个副本:
1
2
3
4
5
|
def
__init__(
self
, passengers
=
None
):
if
passengers
is
None
:
self
.passengers
=
[]
else
:
self
.passengers
=
list
(passengers)
# 使用构造函数复制副本
|
del语句删除的是引用,而不是对象。但是del可能会导致对象没有引用,进而被当做垃圾回收.
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
>>>
import
weakref
>>> s1
=
{
1
,
2
,
3
}
# s2和s1引用同一个对象
>>> s2
=
s1
>>>
def
bye():
...
print
(
"Gone"
)
...
# 监控对象和调用回调
>>> ender
=
weakref.finalize(s1, bye)
>>> ender.alive
True
# 删除s1后还存在s2引用
>>>
del
s1
>>> ender.alive
True
# s2重新绑定导致{1, 2, 3}引用归零
>>> s2
=
"spam"
Gone
# 对象被销毁了
>>> ender.alive
False
|
在CPython中,对象的引用数量归零后,对象会被立即销毁。如果除了循环引用之外没有其他引用,两个对象都会被销毁.
某些情况下,可能需要保存对象的引用,但不留存对象本身。比如,有个类想要记录所有实例。这个需求可以使用弱引用实现.
比如上面示例中的weakref.finalize(s1, bye),finalize就持有{1, 2, 3}的弱引用,虽然有引用,但是不会影响对象被销毁.
其他使用弱引用的方式是WeakDictionary、WeakValueDictionary、WeakSet.
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
class
Cheese:
def
__init__(
self
, kind):
self
.kind
=
kind
def
__repr__(
self
):
return
'Cheese(%r)'
%
self
.kind
>>>
import
weakref
>>> stock
=
weakref.WeakValueDictionary()
>>> catalog
=
[Cheese(
'Red Leicester'
), Cheese(
'Tilsit'
),
... Cheese(
'Brie'
), Cheese(
'Parmesan'
)]
...
>>>
for
cheese
in
catalog:
# 用作缓存
# key是cheese.kind
# value是cheese的弱引用
... stock[cheese.kind]
=
cheese
...
>>>
sorted
(stock.keys())
[
'Brie'
,
'Parmesan'
,
'Red Leicester'
,
'Tilsit'
]
# 删除catalog引用,stock弱引用不影响垃圾回收
# WeakValueDictionary的值引用的对象被销毁后,对应的键也会自动删除
>>>
del
catalog
>>>
sorted
(stock.keys())
# 还存在一个cheese临时变量的引用
[
'Parmesan'
]
# 删除cheese临时变量的引用,stock就完全清空了
>>>
del
cheese
>>>
sorted
(stock.keys())
[]
|
注意不是每个Python对象都可以作为弱引用的目标,比如基本的list和dict就不可以,但是它们的子类是可以的:
1
2
3
4
|
class
MyList(
list
):
pass
a_list
=
MyList(
range
(
10
))
weakref_to_a_list
=
weakref.ref(a_list)
|
本文首先阐述了Python变量全部都是引用的这个事实,这意味着在Python中,简单的赋值是不创建副本的。如果要创建副本,可以选择浅复制和深复制,浅复制使用构造方法、[:]或copy.copy(),深复制使用copy.deepcopy()。del删除的是引用,但是会导致对象没有引用而被当做垃圾回收。有时候需要保留引用而不保留对象(比如缓存),这叫做弱引用,weakref库提供了相应的实现.
参考资料:
《流畅的Python》 。
到此这篇关于Python基础之变量的相关知识总结的文章就介绍到这了,更多相关Python变量内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://www.cnblogs.com/df888/p/14920339.html 。
最后此篇关于Python基础之变量的相关知识总结的文章就讲到这里了,如果你想了解更多关于Python基础之变量的相关知识总结的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How to nest OR statements in JavaScript? 有没有办法做到这一点:
在 JavaScript 中有没有办法让一个变量总是等于一个变量?喜欢var1 = var2但是当var2更新,也是var1 . 例子 var var1 = document.getElementBy
我正在努力理解这代表什么 var1 = var2 == var3 我的猜测是这等同于: if (var2 == var3): var1 = var2 最佳答案 赋值 var1 = var2
这个问题已经有答案了: What does the PHP error message "Notice: Use of undefined constant" mean? (2 个回答) 已关闭 8
我在临时表中有几条记录,我想从每条记录中获取一个值并将其添加到一个变量中,例如 color | caption -------------------------------- re
如何将字符串转为变量(字符串变量--> $variable)? 或者用逗号分隔的变量列表然后转换为实际变量。 我有 2 个文件: 列名文件 行文件 我需要根据字符串匹配行文件中的整行,并根据列名文件命
我有一个我无法解决的基本 php 问题,我也想了解为什么! $upperValueCB = 10; $passNodeMatrixSource = 'CB'; $topValue= '$uppe
这可能吗? php $variable = $variable1 || $variable2? 如果 $variable1 为空则使用 $variable2 是否存在类似的东西? 最佳答案 PHP 5
在 Perl 5.20 中,for 循环似乎能够修改模块作用域的变量,但不能修改父作用域中的词法变量。 #!/usr/bin/env perl use strict; use warnings; ou
为什么这不起作用: var variable; variable = variable.concat(variable2); $('#lunk').append(variable) 我无法弄清楚这一点
根据我的理解,在32位机器上,指针的sizeof是32位(4字节),而在64位机器上,它是8字节。无论它们指向什么数据类型,它们都有固定的大小。我的计算机在 64 位上运行,但是当我打印包含 * 的大
例如: int a = 10; a += 1.5; 这运行得很完美,但是 a = a+1.5; 此作业表示类型不匹配:无法从 double 转换为 int。所以我的问题是:+= 运算符 和= 运算符
您好,我写了这个 MySQL 存储过程,但我一直收到这个语法错误 #1064 - You have an error in your SQL syntax; check the manual that
我试图在我的场景中显示特定的奖牌,这取决于你的高分是基于关卡的目标。 // Get Medal Colour if levelHighscore goalScore { sc
我必须维护相当古老的 Visual C++ 源代码的大型代码库。我发现代码如下: bIsOk = !!m_ptr->isOpen(some Parameters) bIsOk的数据类型是bool,is
我有一个从 MySQL 数据库中提取的动态产品列表。在 list 上有一个立即联系 按钮,我正在使用一个 jquery Modal 脚本,它会弹出一个表单。 我的问题是尝试将产品信息变量传递给该弹出窗
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
jQuery Core Style Guidelines建议两种不同的方法来检查变量是否已定义。 全局变量:typeof variable === "undefined" 局部变量:variable
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: “Variable” Variables in Javascript? 我想肯定有一种方法可以在 JavaScrip
在语句中使用多重赋值有什么优点或缺点吗?在简单的例子中 var1 = var2 = true; 赋值是从右到左的(我相信 C# 中的所有赋值都是如此,而且可能是 Java,尽管我没有检查后者)。但是,
我是一名优秀的程序员,十分优秀!