1.pyc简介
python程序在运行时也有编译过程,编译后会产生.pyc文件。这是一种由python虚拟机执行的二进制文件(字节码),用于保存内存中PyCodeObject,以便加快程序的加载运行。这个文件可以跨平台,但与python版本高度相关(文件名中带有版本信息),不同版本的.pyc内容不同。
怎么见证.pyc文件的存在呢?
方法1:
在python程序中通过import调用其他程序运行时,python会自动生成一个与被调用的python程序文件相关的.pyc文件出来。linux平台和windows平台都OK,生成的文件保存在__pycache__目录中。
注意:
被调用的程序如果修改代码后再次运行,系统会基于时间来检测pyc的可用性并重新生成最新的pyc文件
方法2:
手动编译
>>> import py_compile
>>> py_compile.compile("D:/test.py")>>>批量编译只需要输入对应的目录名称即可
以上内容参考自博客
2.python常用的数据类型及其用法
2.1 数字
数字是一类常见的数据类型,可分为整型、长整型(仅仅在2.x版本中存在该类型)和浮点数等常见的几类。
数字的类型可通过函数type()来确定:
2.2 布尔值
布尔值用来表示true或false,常常用在条件控制语句中作为条件来判断,系统会根据表达式的内容自动判断true或false,也可以通过print打印输出:
>>> print((4+1)<5) False >>>
2.3 字符串
字符串是一类非常常见的数据类型,使用变量、条件判断等都需要使用它。
字符串常见的操作如下:
2.3.1 strip 去除首尾特殊字符
strip可用于去除字符串中首尾的特殊字符,包括空格、换行符等。
>>> a=" this is for test\n">>> print(a) this is for test>>> a=a.strip()>>> print(a)this is for test>>>
应用strip方法后直接去除了首部空格和尾部换行符。
2.3.2 split 按指定分隔符分割字符串
分割后的字符串会以列表形式打印输出
>>> test="Alex Jobs Tim Jack">>> test1=test.split(" ")>>> print(test1)['Alex', 'Jobs', 'Tim', 'Jack']
2.3.3 join 按指定分隔符拼接字符串
语法: 'sep'.join(seq)
参数说明sep:分隔符。可以为空seq:要连接的元素序列、字符串、元组、字典上面的语法即:以sep作为分隔符,将seq所有的元素合并成一个新的字符串
返回值:返回一个以分隔符sep连接各个元素后生成的字符串
可以看出join的操作近似于split的逆向操作。
>>> print(test1)['Alex', 'Jobs', 'Tim', 'Jack'] >>> print(' '.join(test1))Alex Jobs Tim Jack>>>
直接对字符串对象进行拼接处理时每两个相邻的字符之间都会插入分隔符:
>>> print(' '.join("Let'sPython"))L e t ' s P y t h o n>>>
2.3.4 format 格式化替换
>>> message="Hi {name}, Let's {do_something}">>> messageForJack=message.format(name='Jack',do_something='Python')>>> print(messageForJack)Hi Jack, Let's Python>>>
>>> message="Hi {0}, Let's {1}">>> print(message.format('Jack','Python'))Hi Jack, Let's Python>>>
>>> message="Hi {1}, Let's {2}">>> print(message.format('Jack','Python'))Traceback (most recent call last): File "", line 1, in IndexError: tuple index out of range>>>
2.3.5 按索引对字符串切片(切分)
>>> message="Let's Python">>> print(message[6:])Python>>> print(message[:])Let's Python>>> print(message[0:4])Let'>>>
>>> print(message[6:-1])Pytho>>> print(message[6:-2])Pyth>>> print(message[-2:])on>>>
2.3.6 center 字符串居中并均匀填充至指定长度
>>> message="Let's Python">>> test=message.center(20,'*')>>> print(test)****Let's Python****>>> print(message.center(20,'*'))****Let's Python****
>>> print(message.center(20,)) Let's Python>>> print(len(message.center(20,)))20>>>
2.3.7 find 查找字符串中指定的字符
>>> message="Let's Python">>> print(message.find('t'))2>>>
#!/usr/bin/env python# -*- coding:utf-8 -*-message="Let's Python"counter=0flag=0while(message.find('t')) > 0: counter+=1 index=message.find('t') flag=index+1 message=message[flag:]print(counter)
2.3.8 判断字符串的格式或内容
先列举部分,有待完善:
isalnum 判断字符串是否有字母和数字组成
startswith 判断是否以某个字符开头
endswith 判断是否以某个字符结束
upper 所有字母转换成大写
lower 所有字母转换成小写
示例:
>>> test='23edtg9v%'>>> print(test.isalnum())False>>> print(test.startswith('6'))False>>> print(test.endswith('v%'))True>>> print(test.upper())23EDTG9V%>>> print(test.upper().lower())23edtg9v%>>>
2.4 列表list
列表是有序、长度和内容可灵活变化的集合,它由不同的元素按照特定的顺序组合构成,也是python的一种非常典型的数据类型。
2.4.1 创建列表
列表的创建方法如下:
>>> list1 = []>>> list2 = [1,2,3]
方括号表示创建一个列表,可创建一个为空的列表后续赋值,亦可创建时直接赋值。
2.4.2 访问获取列表的元素与切片处理
访问获取列表的单个元素可直接通过索引下标来进行,需要注意的是索引下标从0开始。但对于末尾的元素,下标可逆向用负数来标识。
>>> list2[2]3>>> list2[1]2>>> list2[0]1>>> list2[-1]3>>> list2[-2]2
需要一次性访问获取列表的多个连续元素时,需要通过切片操作来进行。
切片的要点如下:
- 通过起始索引和结束索引位置来访问获取多个元素,获取的元素包括起始索引对应的元素,但不包括结束索引位置对应的元素
- 访问的方向只能从左往右,不能逆向
- 结束位置索引省略不写表示获取的对象包含最后一个元素
- 获取整个元素时可省略起始索引和结束索引位置不写,或者连方括号也省略不写
- 索引值不可超过相应的范围,<=len(list)-1
>>> list2[1:2][2]>>> list2[1:][2, 3]>>> list2[1:-1][2]>>> list2[0:2][1, 2]>>> list2[:][1, 2, 3]>>> list21, 2, 3]
切片操作中可支持连续切片,直到分割为单个字符串为止:
>>> name = ["Jack","Tim","Jessie","Frank","Merry"]>>> name[1:4]['Tim', 'Jessie', 'Frank']>>> name[1:4][1]'Jessie'>>> name[1:4][1][:4]'Jess'>>> name[1:4][1][:4][1]'e'>>> name[1:4][1][:4][1][1]Traceback (most recent call last): File "", line 1, in IndexError: string index out of range>>>
需要注意的是上面第二步切片后获取的是列表的单个元素,如果想继续切片直到分割为单个字符为止,那么在第二步切片时应该使用单个索引小标来访问获取到这个元素,之后再继续切片,否则会得出完全不同的结果:
>>> name[1:4]['Tim', 'Jessie', 'Frank']>>> name[1:4][1:2]['Jessie']>>> name[1:4][1:2][:]['Jessie']>>> name[1:4][1:2][:4]['Jessie']>>> name[1:4][1:2][1:2][]>>> name[1:4][1:2][:]['Jessie']>>> name[1:4][1:2][3]Traceback (most recent call last): File "", line 1, in IndexError: list index out of range
2.4.3 修改某个元素的值
通过下标重新赋值即可:
>>> name = ["Jack","Tim","Jessie","Frank","Merry"]>>> name[0]="Jim">>> name['Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>>
2.4.4 插入新元素
调用insert方法即可:
insert(index, newelement) 第一个参数表示计划插入的下标,第二个参数表示计划插入的具体元素
>>> name = ["Jack","Tim","Jessie","Frank","Merry"]>>> name['Jack', 'Tim', 'Jessie', 'Frank', 'Merry']>>> name.insert(1,"Jim")>>> name['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>>
2.4.5 追加元素
通过append方法即可:
append(newelement) 注意append是将元素追加到末尾,不能像insert一样指定插入的索引位置点
>>> name = ['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>> name.append("Jim2")>>> name['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry', 'Jim2']>>>
注意: 对于定义的空数组,第一次赋值时一定要使用append方法追加,如果使用定义列表的方法赋值会报“IndexError: list assignment index out of range”的错误。
2.4.6 删除元素
删除元素的方法很多,大致列举如下:
remove(element) 传入的参数是元素的具体内容,且每次只能删除一个元素
>>> name = ['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry', 'Jim2']>>> name.remove("Jim2")>>> name['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>>
pop(index) 通过元素的索引下标来进行删除,每次也只能删除一个元素,删除时会显示删除的元素内容;如果下标为空则删除列表的最后一个元素
>>> name = ['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>> name.pop(1)'Jim'>>> name['Jack', 'Tim', 'Jessie', 'Frank', 'Merry']
>>> name.pop()'Merry'>>> name['Jack', 'Tim', 'Jessie', 'Frank']
del 可用于删除内存中的任何数据
>>> name = ['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>> del name>>> print(name)Traceback (most recent call last): File "", line 1, in NameError: name 'name' is not defined>>>
2.4.7 步长
一般用于切片处理,表示针对索引分隔多少个元素。步长不能为0,默认为1(此时相当于普通的切片处理)。
>>> name = ['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>> print(name[::])['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>> print(name[::3])['Jack', 'Jessie']>>>
2.4.8 判断某个元素是否在列表中
使用in操作符来判断某个元素是否在列表中
>>> name = ['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>>>>> 'Alex' in nameFalse>>> 'Alex' not in nameTrue>>>
2.4.9 获取某个元素在列表中的具体索引位置
使用index方法可获取某个元素在列表中的具体索引位置,但需要注意的是如果某个元素多次出现,index方法仅返回第一次匹配到的索引位置
>>> name = ['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry']>>> print("The index is: %s" % name.index('Tim'))The index is: 2>>>
2.4.10 统计某个元素在列表中出现的次数
使用count方法可以统计某个元素在列表中出现的次数
>>> print(name)['Jack', 'Jim', 'Tim', 'Jessie', 'Frank', 'Merry', 'Jim', 'Jim', 'Jim']>>>>>>>>> name.count('Tim')1>>> name.count('Jim')4>>>
2.4.11 合并列表
通过extend方法可将一个列表的元素追加合并到另外一个列表中
list1.extend(list2) 将list2的元素追加合并到list1中
>>> list1=[1,2,3,'Jack','Jim']>>> list2=[4,5,6,'Jessie','Lucy']>>> print(list1)[1, 2, 3, 'Jack', 'Jim']>>> print(list2)[4, 5, 6, 'Jessie', 'Lucy']>>> list1.extend(list2)>>> print(list1)[1, 2, 3, 'Jack', 'Jim', 4, 5, 6, 'Jessie', 'Lucy']>>>
2.4.12 列表排序
使用sort方法可对列表的元素进行正向排序
>>> list3=[11,33,66,22,0,56]>>> print(list3)[11, 33, 66, 22, 0, 56]>>> list3.sort()>>> print(list3)[0, 11, 22, 33, 56, 66]>>>
注意2.0版本可以对字符串和数字混合的列表进行排序,3.0不支持
2.4.13 列表反转
使用reverse方法可以把列表的所有元素倒序反转排列
>>> list3=[11,33,66,22,0,56]>>> print(list3)[11, 33, 66, 22, 0, 56]>>> list3.reverse()>>> print(list3)[56, 0, 22, 66, 33, 11]>>>
2.4.14 列表的嵌套
可根据需要对列表进行自由嵌套处理,需要注意的是此时如果访问被嵌套的列表中的元素,则需要通过多层索引逐级(从外到内)来访问。
>>> list1=['Sichuan','HuBei','GuangDong',['HaiDian','DongCheng','XiCheng'],'Beijing']>>> print(list1)['Sichuan', 'HuBei', 'GuangDong', ['HaiDian', 'DongCheng', 'XiCheng'], 'Beijing']>>> print(list1[3][:])['HaiDian', 'DongCheng', 'XiCheng']>>> print(list1[3][0])HaiDian>>>
2.4.15 列表的浅copy和深copy
对列表进行copy时,存在浅copy和深copy两种方式:
- 浅copy:
对列表进行浅copy时,新的列表只会copy不属于嵌套列表中的元素(即列表中第一层元素),属于嵌套列表中的元素则直接指向它的内存块地址。这样copy前后的两个列表实质是共享同一个被嵌套的列表(内存空间)。在任何一个列表中对被嵌套的元素进行修改后,两个列表中的数据均会同步变化。被嵌套的列表类似于copy前后两个列表的软链接。
这个属于浅copy,可避免被嵌套的列表元素过多而导致copy后占用大量内存资源。
>>> list1=['Sichuan','HuBei','GuangDong',['HaiDian','DongCheng','XiCheng'],'Beijing']>>> print(list1)['Sichuan', 'HuBei', 'GuangDong', ['HaiDian', 'DongCheng', 'XiCheng'], 'Beijing']>>> print(list1[3][:])['HaiDian', 'DongCheng', 'XiCheng']>>> print(list1[3][0])HaiDian>>>>>> list2=list1.copy()>>> print(list2)['Sichuan', 'HuBei', 'GuangDong', ['HaiDian', 'DongCheng', 'XiCheng'], 'Beijing']
现在对被嵌套的元素进行更新处理:
>>> list2[3][0]='ChaoYang'>>> print(list2)['Sichuan', 'HuBei', 'GuangDong', ['ChaoYang', 'DongCheng', 'XiCheng'], 'Beijing']>>> print(list1)['Sichuan', 'HuBei', 'GuangDong', ['ChaoYang', 'DongCheng', 'XiCheng'], 'Beijing']>>>
对比被嵌套的元素更新前后可发现,即便是通过copy后的新列表来对其进行更新处理,这个变化也会立即同步到被copy的源列表中,足以说明被嵌套的列表在两者中其实是共享的一块内存空间。可通过id查看内存地址来验证:
>>> print(id(list1[3]))7463816>>> print(id(list2[3]))7463816>>>
但是注意,仅仅是被嵌套的列表存在共享关系,其他的第一层元素仍然是独立的,整个列表的id二者还是不同:
>>> print(id(list1))18377864>>> print(id(list2))7284680
- 深copy:
不同于浅copy中的共享内存地址空间机制,深copy是针对被copy的列表生成一份完整独立的拷贝,包括被嵌套的列表元素。copy后的新列表与原列表二者相互独立,通过各自专属的内存空间存放。
需要注意的是使用deepcopy时需要先import copy(浅copy中list.copy等同于copy.copy(list1)):
>>> import copy>>> list1=['Sichuan','HuBei','GuangDong',['HaiDian','DongCheng','XiCheng'],'Beiing']>>> print(list1)['Sichuan', 'HuBei', 'GuangDong', ['HaiDian', 'DongCheng', 'XiCheng'], 'Beijing]>>> list3=copy.deepcopy(list1)>>> print(list3)['Sichuan', 'HuBei', 'GuangDong', ['HaiDian', 'DongCheng', 'XiCheng'], 'Beijing]>>> list1[3][0]='ChaoYang' #开始更新被嵌套的列表元素>>> print(list1)['Sichuan', 'HuBei', 'GuangDong', ['ChaoYang', 'DongCheng', 'XiCheng'], 'Beijin']>>> print(list3)['Sichuan', 'HuBei', 'GuangDong', ['HaiDian', 'DongCheng', 'XiCheng'], 'Beijing]>>> list3[0]='HuNan' #更新新列表的元素>>> print(list3)['HuNan', 'HuBei', 'GuangDong', ['HaiDian', 'DongCheng', 'XiCheng'], 'Beijing']>>> print(list1)['Sichuan', 'HuBei', 'GuangDong', ['ChaoYang', 'DongCheng', 'XiCheng'], 'Beijing']>>> list1[0]='ZheJiang' #更新被拷贝的列表的元素>>> print(list1)['ZheJiang', 'HuBei', 'GuangDong', ['ChaoYang', 'DongCheng', 'XiCheng'], 'Beijing']>>> print(list3)['HuNan', 'HuBei', 'GuangDong', ['HaiDian', 'DongCheng', 'XiCheng'], 'Beijing']>>>
通过上述更新过程可发现,执行deepcopy后两者之间是完全独立的,可通过id来验证:
>>> print(id(list1))18377864>>> print(id(list3))7307528>>>>>> print(id(list1[3]))7463816>>> print(id(list3[3]))7463932
2.4.16 列表的遍历
常用的遍历列表方法有如下两种:
方法一:
通过简单的for循环,逐个打印出列表元素(不能打印索引):
members = ['Tim', 'Jack', 'Frank', 'July', 'Alex', 'Tim', 'Susan']for i in members:print(i)
输出结果为:
TimJackFrankJulyAlexTimSusan
方法二:
通过enumerate函数和for循环,同时逐个打印索引和索引对应的元素:
members = ['Tim', 'Jack', 'Frank', 'July', 'Alex', 'Tim', 'Susan']for i, j in enumerate(members):print(i, j)
输出结果为:
0 Tim1 Jack2 Frank3 July4 Alex5 Tim6 Susan
注意:
如果list的元素是由元组(tuple)有规律地嵌套组成,则可以通过简单的for循环逐个取出每个元组(每个元素)的值,实质上类似于方法一,只不过每次取一个tuple对应的值,实际分解出来是两个值:
members = [('Tim', 'male'), ( 'Jack', 'male'), ('Frank', 'male'),('Susan', 'female')]print(members)for member, gender in members:print(member, gender)
输出结果为:
[('Tim', 'male'), ('Jack', 'male'), ('Frank', 'male'), ('Susan', 'female')]Tim maleJack maleFrank maleSusan female
2.5 元组tuple
元组即其他语言中的数组,元组与列表的区别是,一旦定义后不可更改对元素的指向(并非元素一旦定义就不可更改),相当于只读列表。
如何理解一旦定义后就不可更改对元素的指向呢?tuple的每个元素,指向永远不变。即指向'a',就不能改成指向'b',指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!这个指向不可改变的好处是代码更安全,如果可能,能用tuple代替list就尽量用tuple。
元组只支持count和index函数,也可以通过索引来获取元素。
定义元组的方法如下:
>>> members=('Tim','Jack','Suse','Mar')
>>> print(members) ('Tim', 'Jack', 'Suse', 'Mary')
或者通过tuple关键字加双括号来定义:
>>> Lanauge=tuple(('Python','Java','PHP'))>>> print(Lanauge)('Python', 'Java', 'PHP')>>>
count和index的使用如下:
>>> print(members.count('Jack'))1>>> print(members.index('Jack'))1>>> print(members.index('Suse'))2>>>
2.6 字典
字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据。python对key进行哈希函数运算,根据计算的结果决定value的存储地址,所以字典是无序存储的,且key必须是可哈希的。可哈希表示key必须是不可变类型,如:数字、字符串、只含不可变类型元素的元组(1,2,3,’abc’)、实现__hash__()方法的自定义对象(因为__hash__()须返回一个整数,否则会出现异常:TypeError: an integer is required)。
由于采用key-value键值对存储,因此在同一个字典中key必须唯一。
2.6.1 字典的定义
字典可通过一对花括号来定义,元素内部通过冒号来连接key和对应的value,元素与元素之间通过逗号隔开,可进行自由嵌套。
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> print(dict1){ 'Name': 'Alex', 'Sex': 'Male', 'Add': 'Beijing'}>>>
2.6.2 字典的常用操作
访问、修改、删除字典的某个元素,都通过key来实现
访问:
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> print(dict1['Sex'])Male>>>
更新修改:
>>> dict1['Name']='Alice'>>> dict1['Sex']='Female'>>> print(dict1){ 'Name': 'Alice', 'Sex': 'Female', 'Add': 'Beijing'}>>>
删除, 可通过del或者调用字典的pop方法来实现
>>> del dict1['Add']>>> print(dict1){ 'Name': 'Alice', 'Sex': 'Female'}>>> dict1.pop('Sex')'Female'>>> print(dict1){ 'Name': 'Alice'}>>>
获取字典的长度(键值对的个数),通过len方法实现:
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> print(len(dict1))3>>>
通过sorted方法对所有的key进行排序并以列表形式返回:
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> sorted(dict1)['Add', 'Age', 'Name', 'Sex']>>>
2.6.3 字典的常用内置方法
keys --以列表形式返回字典的所有key:
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> dict1.keys()dict_keys(['Name', 'Sex', 'Add'])>>>
values --以列表形式返回字典的所有value:
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> dict1.values()dict_values(['Male', 'Alex', 'Beijing'])>>>
items --返回一个包含键值元组的列表
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> dict1.items()dict_items([('Sex', 'Male'), ('Name', 'Alex'), ('Add', 'Beijing')])>>>
get -- dict.get(key,default=None) 返回指定key对应的value,若key不存在则返回默认指定的值(仅仅是返回而已,不会修改原字典),可用于判断某个key是否在字典中。
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> dict1.get('Age',22)22>>> print(dict1){ 'Sex': 'Male', 'Name': 'Alex', 'Add': 'Beijing'}>>>
setdefault -- dict.setdefault(key,default=None) 若key在字典中存在,则用默认值覆盖更新原值,否则直接添加键值对到原字典中。
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> dict1.setdefault('Age',22)22>>> print(dict1){ 'Sex': 'Male', 'Age': 22, 'Name': 'Alex', 'Add': 'Beijing'}>>>
update -- dict1.update(dict2) 将字典dict2的键值对复制添加到字典dict1中
>>> dict1={ 'Name':'Alex','Sex':'Male','Add':'Beijing'}>>> dict2={1:'Beijing',2:'Shanghai',3:'Guangzhou'}>>> dict1.update(dict2)>>> dict1{ 3: 'Guangzhou', 1: 'Beijing', 'Add': 'Beijing', 'Age': 22, 'Sex': 'Male', 'Name': 'Alex', 2: 'Shanghai'}
2.6.4 字典与列表的对比
字典的特殊性在于,内部存放的顺序与key存入的顺序没有任何关系,因为它本身就是无序的。
字典与列表对比特点如下:
字典:
查找和插入的速度极快,不会随着key的增加而变慢
需要占用大量的内存(浪费比较多)
列表:
查找和插入的时间随着元素的增加而增加
占用空间小,内存浪费少
综上所述,字典是在用空间换取时间(执行效率)。
3.python常用的运算符
3.1 数据运算
3.2 比较运算
3.3 赋值运算
3.3 逻辑运算
逻辑运算符可以直接使用在if条件判断中,示例如下:
if 2 > 1 and not 2 > 3: print("2 is the middle between 1 and 3")else: print("Error")
3.4 成员运算
判断某个元素是否在列表中即使用in操作符来实现。
>>> list1=['Python','PHP','Ruby']>>> print(list1)['Python', 'PHP', 'Ruby']>>> 'Java' in list1False>>> 'Java' not in list1True>>>
3.5 身份运算
用于判断两个对象的引用关系。
3.6 位运算
按位取反的结果,就是二进制反码对应的十进制减掉256后的结果。