Python学习笔记
- 手动安装包:python -m pip install
- 1. os
- 2. yield,迭代器与生成器(iter,yield,next())
- 3. time模块:与时间相关功能,datetime模块
- 4. print().format()
- 5. sorted函数
- 6. isinstance
- 7. clmp()和clmp_(),加 _ 的区别
- 8. enumerate
- 9. zip
- 10. lambda,map
- 11. shlex,subprocess
- 12. parse
- 13. python中 r'', b'', u'', f'' 的含义
- 14. 关于class
- 14.1 Class在__init__内和__init__外定义变量的区别
- 14.2 关于class的属性
- 15. Python中函数 eval 和 ast.literal_eval 的区别详解
- 16. Pycharm批量修改变量名
- 17. def fun(path: str = 'default') -> str:
- 18. 理解Python_魔法方法__call__
- 19. Python 3 字符串 rsplit( ) 方法
- 20. Python中的index方法
- 21. numpy 数组X[:,0]和X[:,1]的详解
- 22. Python打印动态百分比进度print("\rXXXXX",end="")——使用\r
- 23. Python中list列表、元组、字典前面加星号是什么意思?【\* , \**】
- 26. python之' '.join()函数的用法
- 27. y = x if ? else ?
- 28. python--什么是闭包?
- 29. Python中的不可变对象和可变对象
手动安装包:python -m pip install
- python 手动利用pip安装包
python -m pip install --user ****
(不能联网时可以用这个)- pip使用指南——user选项
- 创建虚拟环境——virtualenv
- 安装 virtualenv,
pip install --user virtualenv
- 使用
virtualenv
创建虚拟环境和使用conda
创建虚拟环境,还是有区别的。使用virtualenv
创建的虚拟环境,环境应该是和项目在同一个目录下面。 - 示例《Python编程:从入门到实践》:
要使用Django,首先需要建立一个虚拟工作环境。虚拟环境是系统的一个位置,你可以在其
中安装包,并将其与其他Python包隔离。将项目的库与其他项目分离是有益的,且为了在第20章将“学习笔记”部署到服务器,这也是必须的。
1. os
参考资料
Python OS 文件/目录方法os.path — Common pathname manipulationsos.path里面,.表示当前目录,…表示上一级目录(os.path.pardir就是表示这个字符串)
import os # os.path模块主要用于文件的属性获取
# os.path.abspath(path)返回path的绝对路径
filename = os.path.abspath('G:/wav/yuyin/yuyin1.wav')
print(filename)
# os.path.split(path)将path分割成目录和文件名并以元组方式返回
filename = os.path.split('G:\wav\yuyin\yuyin1.wav')
print(filename)
# os.path.dirname(path)返回path的目录,其实就是返回os.path.split(path)元组的第一个元素
filename = os.path.dirname('G:\wav\yuyin\yuyin1.wav')
print(filename)
# os.path.basename(path)返回path的文件名,其实就是返回os.path.split(path)元组的第二个元素
filename = os.path.basename('G:\wav\yuyin\yuyin1.wav')
print(filename)
# os.path.commonprefix(list)
# list里面每一个元素都是一个路径,然后这个函数返回路径中的公共路径
list = ["E:\\my_project","E:\\my_project\\darknet","E:\\my_project\\darknet\\darknet-master"]
filename = os.path.commonprefix(list)
print(filename)
# os.path.exists(path)如果path是一个存在的路径,返回True,否则(otherwise) 返回 False
filename = os.path.exists('G:\wav\yuyin\yuyin1.wav')
print(filename)
filename = os.path.exists('G:\wav\yuyin\yuyin111.wav')
print(filename)
# 应用六:判断路径是否存在,不存在则创建:
"""
log_dir = "logs/"
if not os.path.exists(log_dir):
os.makedirs(log_dir)
"""
# os.path.isabs(path)如果路径path是绝对路径返回True,否则(otherwise)返回False
# os.path.isfile(path)如果path是一个存在的文件,返回True,否者(otherwise)返回False
# os.path.isdir(path)如果path里面存在目录,返回True,否则返回False
"""os.path.join(path[,path2[,...])组合多个路径并返回"""
# os.path.splitdrive(path)返回(drivename,fpath)的元组,也就是将驱动磁盘和文件路径split一下返回元组
# os.splitext(path) 分离扩展名然后按照元组返回
# os.path.getsize(path)返回path文件的字节大小,可以传入绝对路径和相对路径
"""应该注意一下的就是os.path.exists(path)和os.path.isfile(path),前者是判断路径是否存在,后者是判断该文件是否存在。"""
2. yield,迭代器与生成器(iter,yield,next())
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
—
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
- 举栗
def func():
for i in range(0, 3):
yield i
fs = func()
print(fs)
for f in fs:
print(f)
"""
out:
<generator object func at 0x000002ABC4466648>
0
1
2
"""
"""
yield在函数中的功能类似于return,不同的是yield每次返回结果之后函数并没有退出,而是每次遇到yield关键字后返回相应结果,并保留函数当前的运行状态,等待下一次的调用。如果一个函数需要多次循环执行一个动作,并且每次执行的结果都是需要的,这种场景很适合使用yield实现。
包含yield的函数成为一个生成器,生成器同时也是一个迭代器,支持通过next方法获取下一个值。
"""
- 举栗2:
def infinite_iter(iterable):
"""qiu-10-26: used in # solver. def get_data_loaders(self)"""
it = iter(iterable)
while True:
try:
ret = next(it)
#print(ret)
yield ret
except StopIteration:
it = iter(iterable)
iterable = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
data = infinite_iter(iterable)
for i in range(5):
data2 = next(data)
print(data2)
3. time模块:与时间相关功能,datetime模块
from datetime import datetime
start = datetime.now()
for i in range(100000000):
pass
et = datetime.now() - start
et = str(et)[:-7]
log = "Elapsed [{}]".format(et)
print(log)
'''
time模块:与时间相关的功能
三种时间类型:
1.时间戳(timestamp):从1970-01-01 到现在的秒数,用于取时间差
time.time():用来计算时间间隔,返回浮点型
2.本地时间(localtime):计算机当前所在位置的时间
time.localtime():返回结构化时间
3.世界协调时间(UTC)
time.gmtime():返回结构化时间
常用方法总结:
1.时间戳:time.time()
应用:用来计算时间间隔
2.结构化时间:time.localtime() time.gtime()
应用:1.单独获取当前时间的任意部分
2.用来时间戳与格式化输出时间之间的转换
3.格式化的字符串形式:time.strftime('%Y-%m-%d')
应用:方便的取出格式化字符串形式的时间,用来显示
datetime模块 vs time模块
1.日期计算比time模块方便
datetime.datetime.now()+datetime.timedelta(days=3)
2.时间戳转换成字符串日期时间
datetime.datetime.fromtimestamp(123123123)
'''
import time
print(time.time())
# 1536136291.5491552
print(time.strftime('%Y-%m-%d %X'))
# 2018-09-05 16:31:31
print(time.localtime())
# time.struct_time(tm_year=2018, tm_mon=9, tm_mday=5, tm_hour=16, tm_min=31, tm_sec=31, tm_wday=2, tm_yday=248, tm_isdst=0)
print(time.gmtime())
# time.struct_time(tm_year=2018, tm_mon=9, tm_mday=5, tm_hour=8, tm_min=31, tm_sec=31, tm_wday=2, tm_yday=248, tm_isdst=0)
# 格式化输出日期
print(time.strftime('%Y-%m-%d %X'))
# 2018-09-05 16:31:31
# 将格式化字符串的时间转换为结构化时间
print(time.strptime("30 Nov 00", "%d %b %y"))
# time.struct_time(tm_year=2000, tm_mon=11, tm_mday=30, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=335, tm_isdst=-1)
# 时间戳转结构化,参数为秒数,即1970年01-01过参数秒的结构化时间输出
print(time.localtime(10))
# time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=0, tm_sec=10, tm_wday=3, tm_yday=1, tm_isdst=0)
# 结构化转时间戳
print(time.mktime(time.localtime()))
# 1536136291.0
# 当前进程睡眠一段时间,单位为秒 time.sleep()
time.sleep(2)
# 返回 星期英文简写 月 日 时间 年(Thu Aug 9 09:11:42 2018)
print(time.asctime())
# Wed Sep 5 16:31:33 2018
print(time.ctime())
# Wed Sep 5 16:31:33 2018
'''
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%M 分钟数(00=59)
%m 月份(01-12)
%D 08/09/18 本地相应的日期表示
%d 月内中的一天(0-31)
%x 本地相应的日期表示
%X 本地相应的时间表示
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%Z 当前时区的名称
%% %号本身
'''
4. print().format()
print('{0},{1}'.format('zhangk', 32))
print('{},{},{}'.format('zhangk','boy',32))
print('{name},{sex},{age}'.format(age=32,sex='male',name='zhangk'))
# 格式限定符
# 它有着丰富的的“格式限定符”(语法是{}中带:号),比如:
# 填充与对齐
# 填充常跟对齐一起使用
# ^、<、>分别是居中、左对齐、右对齐,后面带宽度
# :号后面带填充的字符,只能是一个字符,不指定的话默认是用空格填充
print('{:>8}'.format('zhang'))
print('{:0>8}'.format('zhang'))
print('{:a<8}'.format('zhang'))
print('{:p^10}'.format('zhang'))
# 精度与类型f
# 精度常跟类型f一起使用
print('{:.2f}'.format(31.31412))
# 其他类型
# 主要就是进制了,b、d、o、x分别是二进制、十进制、八进制、十六进制
print('{:b}'.format(15))
print('{:d}'.format(15))
print('{:o}'.format(15))
print('{:x}'.format(15))
# 用逗号还能用来做金额的千位分隔符
print('{:,}'.format(123456789))
5. sorted函数
Python sorted() 函数 sorted() 函数对所有可迭代的对象进行排序操作。
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
6. isinstance
Isinstance的用法是用来判断一个量是否是相应的类型,接受的参数一个是对象加一种类型。示范代码如下:
a = 1
print(isinstance(a,int))
print(isinstance(a,float))
返回 True False
7. clmp()和clmp_(),加 _ 的区别
原文链接:
任何可以改变tensor内容的操作都会在方法名后加一个下划线’_’
例如:x.copy_(y), x.t_(), 这俩都会改变x的值
在pytorch中,我们需要注意,对于tensor的操作时候是in-place类型。
in-place类型是指,在一个tensor上操作了之后,是直接修改了这个tensor。
非in-place类型,是指返回一个新的tensor,而旧的tensor并不修改。
pytorch中,一般来说,如果对tensor的一个函数后加上了下划线,则表明这是一个in-place类型旧的tensor也修改了,
如:
clamp 和 clamp_ (以下为实际例子)
8. enumerate
enumerate 函数用于遍历序列中的元素以及它们的下标;
在迭代一个序列的同时跟踪正在被处理的元素索引。
enumerate(sequence, [start=0])
作用: 将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。 参数: sequence – 一个序列、迭代器或其他支持迭代对象。 start – 下标起始位置。
9. zip
10. lambda,map
11. shlex,subprocess
Python shlex 模块Python3 subprocess
12. parse
import argparse
def main():
"""
1、argparse 是python自带的命令行参数解析包,可以用来方便地读取命令行参数
2、ArgumentParser类生成一个parser对象
3、通过对象的add_argument函数来增加参数,这里增加了两个参数
4、其中'-n','--name'表示同一个参数,default参数表示我们在运行命令时若没有提供参数,程序会将此值当做参数值
5、当'-'和'--'同时出现的时候,系统默认后者为参数名,前者不是,但是在命令行输入的时候没有这个区分
6、最后采用对象的parse_args获取解析的参数
"""
parser = argparse.ArgumentParser(description='This is a description of argparse')
parser.add_argument('-n', '--name', type=str, help='help document', default='Li si')
parser.add_argument('--age', default='18')
args = parser.parse_args()
print(args)
name = args.name
age = args.age
print('The usr is {}, age:{}'.format(name, age))
if __name__ == '__main__':
main()
# 文件名为:demo.py
# 方法一,执行命令:python demo.py # 使用默认参数
# 方法二,执行命令:python demo.py --name Zhangsan --age 20 # 传入参数
# 执行命令:python demo.py -h 可以查看帮助信息
13. python中 r’’, b’’, u’’, f’’ 的含义
python中 r’’, b’’, u’’, f’’ 的含义
14. 关于class
14.1 Class在__init__内和__init__外定义变量的区别
- 变量定义在__init__之外, 该变量隶属于这个类.
- 变量定义在__init__之内, 该变量隶属于这个实例对象.
实例:
class Book(object):
count = 100
def __init__(self, id, name):
self.book_id = id
self.book_name = name
def __add__(self, other):
return self.count + other.count
def show_info(self):
return (self.book_id, self.book_name, self.count)
b1 = Book(1, "b1")
b2 = Book(2, "b2")
sales_cnt = b1 + b2
print(sales_cnt)
count变量:不需要实例化就可以定义
Book.count = 200 # 不实例化改变count的初始变量,将改变全局所有实例的该默认取值
b1.count = 300 # 实例化改变b1这个示例的取值
id和name变量:只能且必须通过实例化进行定义,不得为空
b1 = Book(1, "b1")
b2 = Book(2, "b2")
b1.id = 3 # 只能通过实例化改变b1这个示例的取值
14.2 关于class的属性
- delattr(), 从class的定义中删除某个属性
- hasattr(),判断class中是否含有某个属性
- getattr(),获取某个示例的某个属性值
- isinstance(), 判断是否含有这个class的实例
15. Python中函数 eval 和 ast.literal_eval 的区别详解
一、eval 函数
Python中,如果要将字符串型的 list,tuple,dict 转变成原有的类型呢 ?
这个时候你自然会想到eval
eval函数在 Python 中做数据类型的转换还是很有用的。
它的作用就是把数据还原成它本身或者是能够转化成的数据类型。
16. Pycharm批量修改变量名
IDEA 如何批量修改变量名
在IDEA中进行工作时,有事敲了很久代码发现一个类名,方法名,或者变量名定义错了,这时,该变量可能在很多地方都引用到了,要修改的话,极其麻烦,需要将所有引用该变量的地方都进行修改,特别麻烦。
实际上,IDEA提供了一个快捷键进行变量名的批量处理。
选中修改对象: shift + F6
17. def fun(path: str = ‘default’) -> str:
def fun(path: str = 'default') -> str:
return path
print(fun(), fun('传入一个路径'))
fun_2 = lambda a, b: a + b # lamnda表达式
print(fun_2(1, 2))
结果:
default 传入一个路径
3
18. 理解Python_魔法方法__call__
- 概述:
Python有很多内置魔法方法,一般表现为双下划线开头和结尾。例如 __name__、__doc__、__new__、__init__、__call__等,这些魔法方法会让对象持有特殊行为,今天就介绍,自己平时使用比较多的__call__,我称它为:实例魔法方法。
- 使用方法
什么叫实例魔法方法呢?,就是它可以把类实例当做函数调用。
- 例子
class Bar:
def __call__(self, *args, **kwargs):
print('i am instance method')
b = Bar() # 实例化
b() # 实例对象b 可以作为函数调用 等同于b.__call__ 使用
# OUT: i am instance method
# 带参数的类装饰器
class Bar:
def __init__(self, p1):
self.p1 = p1
def __call__(self, func):
def wrapper():
print("Starting", func.__name__)
print("p1=", self.p1)
func()
print("Ending", func.__name__)
return wrapper
@Bar("foo bar")
def hello():
print("Hello")
# 上面的语法糖写法 等价于 hello = Bar('foo bar')(hello)
if __name__ == "__main__":
hello()
#OUT
Starting hello
p1= foo bar
Hello
Ending hello
- 执行
实例变为可调用对象,与普通函数一致,执行的逻辑是call 函数内部逻辑。
- 优点
代码逻辑很复杂时,不适合写成一个函数内,会封装成类,调用该类对象时,我们直接使用实例作为函数引用,更方便简洁.
通过call 实现类装饰器.
19. Python 3 字符串 rsplit( ) 方法
语法格式:
str.rsplit(sep=None, maxsplit=-1)
描述:
- 返回一个由字符串内单词组成的列表,使用 sep 作为分隔字符串。
- 如果给出了 maxsplit,则最多进行 maxsplit 次拆分,从 最右边 开始。
- 除了从右边开始拆分,rsplit( ) 的其他行为都类似于 split( )。
参数说明:
- sep —— 分隔符,默认为所有的空格符,包括空格、换行(\n)、制表符(\t)等。
- maxsplit —— 分割次数。默认为 -1,即分隔所有。
- 返回值:
返回分割后的字符串列表。
示例:
dir = ['data/speakers/aaa', 'data/speakers/bbb']
all_speaker = [s.rsplit('/', maxsplit=1) for s in dir]
print(all_speaker)
all_speaker_1 = [s.rsplit('/', maxsplit=1)[0] for s in dir]
print(all_speaker_1)
all_speaker_2 = [s.rsplit('/', maxsplit=1)[1] for s in dir]
print(all_speaker_2)
结果:
[['data/speakers', 'aaa'], ['data/speakers', 'bbb']]
['data/speakers', 'data/speakers']
['aaa', 'bbb']
20. Python中的index方法
- 很多时候当要在列表中查找某个元素并输出对应的索引值(位置),这时就需要使用到index()方法了。
https://www.runoob.com/python/att-string-index.html描述
Python index() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,该方法与 python find()方法一样,只不过如果str不在 string中会报一个异常。
语法
index()方法语法:
str.index(str, beg=0, end=len(string))
参数
- str – 指定检索的字符串
- beg – 开始索引,默认为0。
- end – 结束索引,默认为字符串的长度。
返回值
如果包含子字符串返回开始的索引值,否则抛出异常。
实例2:
arrs = ['first', 'second', 'third', 'forth']
arr = 'second'
print(arrs.index(arr)) # 1
print(arrs.index('first')) # 0
21. numpy 数组X[:,0]和X[:,1]的详解
import numpy as np
X = np.array ([[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15], [16, 17], [18, 19]])
# X[:,0]就是取所有行的第0个数据
print(X[:, 0])
#输出:[ 0 2 4 6 8 10 12 14 16 18]
# X[:,1]就是取所有行的第0个数据
print( X[:,1])
#输出:[ 1 3 5 7 9 11 13 15 17 19]
#X[1,:]第一维中下标为1的元素的所有值
print(X[1,:])
#输出:[2 3]
Y = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13,14],[15,16,17],[18,19,20]])
#Y[:, m:n],即取所有数据的第m到n-1列数据,含左不含右
print (Y[:,1:3])
'''
输出:
[[ 1 2]
[ 4 5]
[ 7 8]
[10 11]
[13 14]
[16 17]
[19 20]]
'''
22. Python打印动态百分比进度print("\rXXXXX",end="")——使用\r
Python打印百分比进度
首先,我们先看一下回车符"\r"的含义
查阅资料,发现:
\r 表示将光标的位置回退到本行的开头位置
\b 表示将光标的位置回退一位
然后当print
函数指定end=""
时,表示不换行,再使用"\r"
将光标移至当前行首,相当于覆盖了之前打印出来的东西,看起来就相当于只有百分比在变化.
实例:
import time
for i in range(100):
print("\r进度为%d%%"%i,end="")
#每打印一次休息0.1秒,方便人眼观察(仅此示例用)
time.sleep(0.1)
#此时可以看见打印出了“动态的”百分比进度
23. Python中list列表、元组、字典前面加星号是什么意思?【* , **】
列表、元组前面加星号作用是将列表解开成两个独立的参数,传入函数,字典前面加两个星号,是将字典解开成独立的元素作为形参。
1、列表
def add(a, b):
return a+b
data = [1,2,4,3]
print("原始列表:", data)
print("列表前加*:" ,*data)
结果:
原始列表: [1, 2, 4, 3]
列表前加*: 1 2 4 3
2、字典1
data = {'a' : 4, 'b' : 3}
print("原始字典:", data)
print("字典前加*:" , *data)
结果:
原始字典: {'a': 4, 'b': 3}
字典前加*: a b
2.1、字典中,两个** 用法
# ** 的用法, 拆成关键字形参
config = {'SpeakerEncoder': {'c_in': 512, 'c_h': 128, 'c_out': 128, 'kernel_size': 5, 'bank_size': 8}}
print("*config['SpeakerEncoder']: ", *config['SpeakerEncoder'])
def fun(c_in, c_h, c_out, kernel_size, bank_size):
print("**config['SpeakerEncoder']: ", c_in, c_h, c_out, kernel_size, bank_size)
fun(**config['SpeakerEncoder'])
结果:
*config['SpeakerEncoder']: c_in c_h c_out kernel_size bank_size
**config['SpeakerEncoder']: 512 128 128 5 8
3、注意:
- 可迭代对象才可以使用*号拆分;
- 带*号变量严格来说并不是一个变量,而更应该称为参数,它是不能赋值给其他变量的,但可以作为参数传递;
举例:
def add(a, b):
return a+b
data = [4,3]
print (add(*data))
26. python之’ '.join()函数的用法
1.''.join()
函数的用法
描述:
- Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符
join()方法语法:
str.join(sequence)
参数
- sequence – 要连接的元素序列。
返回值
- 返回通过指定字符连接序列中元素后生成的新字符串。
实例
#!/usr/bin/python3
s1 = "-"
s2 = ""
seq = ("r", "u", "n", "o", "o", "b") # 字符串序列
print (s1.join( seq ))
print (s2.join( seq ))
结果:
r-u-n-o-o-b
runoob
27. y = x if ? else ?
k = True
j = False
x = 1 if k else 2
y = 1 if j else 2
print("x: ", x)
print("y: ", y)
结果:
x: 1
y: 2
28. python–什么是闭包?
闭包的定义:
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。
闭包就是装饰器的本质。
构成条件:
通过闭包的定义,我们可以得知闭包的形成条件:
- 在函数嵌套(函数里面再定义函数)的前提下
- 内部函数使用了外部函数的变量(还包括外部函数的参数)
- 外部函数返回了内部函数
注:可以将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成,外函数和内函数。在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
示例:
29. Python中的不可变对象和可变对象
彻底理解Python中的"指针"众所周知,Python中一切皆对象,每个对象至少包含三个数据:引用计数、类型和值。引用计数用于Python的GC机制,类型用于在CPython层运行时保证类型安全性,值就是对象关联的实际值。
Python对象分为不可变对象和可变对象。可变对象可以修改,上面第一个例子中的test_list(list类型)就属于可变对象,不可变对象无法更改,类似C语言中加了const修饰,上面第二个例子中的test_value(int类型)就属于不可变对象。
不可变对象:int(整形)、str(字符串)、float(浮点型)、tuple(元组)
可变对象:dict(字典)、list(列表)、 set(集合)