提高健壮性
如果 try 结构的位置不当,可能导致死循环等问题。
file_name=input('请输入文件名:')
try:
with open(file_name) as f:
#用with的方式读写更加安全
#因为出错可能在打开时,可能是关闭时
#所以这样读写能保证正确处理
print('你好')
except (FileNotFoundError,FileExistsError):
#用元组放错误类型
print('文件不存在')
except ZeroDivisionError:
print('文件中没有数据')
except Exception as e:
#所有异常都属于Exception类
print('特殊错误:',e)
else:
print('没有任何异常才会到这句话')
finally:
print('有没有异常都会执行这句话!')
#这句话必须执行,甚至会影响语句上面的return语句
题目:比较销量
编写一个程序读取该文件的每一行记录;对于每一条记录,如果其数字健全并且格式正确,则在屏幕上输出该产品A地区销量与B地区销量的比例;否则提示该产品无法计算,然后跳过这一行,继续检查计算下一条记录。
file_name=input('请输入文件名:')
with open(file_name) as f:
for i in f.readlines():
try:
#try写在这里面,再次循环扫下一行才行
s=i.split(',')
print(s[0],'在AB两地区的销量分别为',format(float(s[1].strip())/float(s[2].strip()),'0.2f'))
except Exception as err:
print(s[0],'该行数据存在问题')
如果想自己测试,可以手动通过raise关键字来人为添加异常
raise ZeroDivisionError('除数为0异常')
Traceback (most recent call last):
File "E:/拷贝过来的文件/全民一起玩Python/MyProject/实战案例/小甲鱼练习.py", line 1, in <module>
raise ZeroDivisionError('除数为0异常')
ZeroDivisionError: 除数为0异常
作用域和类型函数
- 用 type(x) 可以得到一个type类对象,该对象的属性中保存了名称 x 的数据类型信息。特别是该对象的 name 属性,就是变量 x 的类型名称。比如 type(3.14).name 得到的就是字符串 ‘float’
- 由于 type 函数将类型名称作为字符串返回,所以实际编程时容易因为字符串笔误等原因造成隐患;同时该函数无法用于分辨一个类型是否属于其父类(比如bool类型数据True是否也是一个int类型的数据),因此一般更推荐使用 isinstance 函数。
- isinstance(x, 类型名) 可以返回一个逻辑值True或False,代表x是否属于指定类型。其中类型名不是字符串形式,而是直接书写,比如 isinstance(x, int) 。
- 变量从被首次赋值起正式创建可用,针对该变量的第一条赋值语句,相当于该变量的定义或声明。在变量赋值之前,尝试使用该变量会导致错误。
- 在模块中定义的变量,其作用域是整个模块,即该模块中的所有代码都可以使用该变量(对于该模块中的函数相对特殊,请见后几条笔记);而定义在函数和类中的变量,其作用域只是该函数或类,外部代码无法访问。
- 作用域只有模块、函数和类几种区别,而 if、for、while、try…catch 等流程结构并不影响作用域。
- 模块中只能调用本模块全局变量,无法调用函数等作用域内部的局部变量。
- 函数内部如果没有赋值过与全局变量同名的变量,则可以读取该全局变量的数值。
- 如果函数内部通过指定参数名、赋值语句或for循环等方式定义了自己的局部变量,则该函数内部无法读取修改与之同名的全局变量。注意:即使函数中没有使用赋值语句,但只要该名字出现在函数的参数列表中,或者是 for 循环的循环变量,也相当于赋值、会创建相应的局部变量。
- 如果在函数中先使用 global 关键字对某个变量进行特别声明,则该函数中所用到的这个变量名,一律指代全局变量,即使赋值也不会创建新的局部变量。
变量的一些原理
程序运行时,Python会在内存中维护一个“变量表”。里面每条记录都保存了一个变量的信息.其中关键两个信息是该变量的名字、该变量所指向的内存地址号码,而该变量的真实取值则存放在该地址号码指向的内存单元。当 Python 需要读取数据时,首先根据变量名得到这个地址,然后再根据该地址,找到真实数据。类似于C语言的指针
使用内置函 id() 可以取出一个变量所指向的地址号码。在使用官方解释器 CPython 时,id 函数返回的这个数字就是内存地址。
修改一个变量的取值时,Python 只是修改了这个变量所存储的地址号码,从而让它指向新数值的所在位置,并不会修改原来那个位置的原数值。原数值将一直保留在其内存单元中,直到Python将其收回。
使用 is 可以比较两个变量是否指向同一地址,即其 id 是否相同。
对于 a 和 b 两个变量,如果 a is b 为 True,则 a== b 一定为 True;反之如果 a==b 为True,a is b 有可能是 False。
a=400
b=400
a is b
False
a==b
True
为提高程序效率,Python会预先创建好 -5 至 256 范围内的常用小整数,保存在内存中固定位置。当程序用到这些整数时,不必再次重复创建,因而执行 a=3 和 b=1+2 后,a 与 b 指向同一内存地址,即 a is b 返回 True。
y=id(x)
y
8791415183040
x=x+1
y=id(x)
y
8791415183072
x=x-1
y=id(x)
y
8791415183040
比较一下上下的代码
y
59421904
x=x+1
y=id(x)
y
58453296
x=x-1
y=id(x)
y
58453232
当在程序中创建一个字符串并赋值给某个变量时,Python会先检查内存中是否已经存在同样内容的字符串。如果已经存在,则不会再重复创建,而是让该变量直接指向这个已存在的字符串。
但是对于含有特殊字符以及中文等文本的字符串,Python不会按此机制检查,即使内存中已经存在相同内容,也会直接创建一个新的字符串对象。
如果将一个变量赋值为容器(比如列表),那么这个变量的门牌号会指向内存中一个较大的空间,也就是容器所在位置。而这个位置的内存中也存放有多个地址数字,每个地址再指向另外一处内存,也就是容器中每个元素的数值存放位置。
如果一块内存中保存了数字或字符串,那么这块内存就不再允许修改;那如果其中保存的是列表,那么其内部存储的各个地址号码都允许修改,以便使对应元素指向其他数值。在Python中,我们将前者称为“不可变对象”,后者称为“可变对象”。
>>> a=[1,2,3]
b=a
b.extend([4,5])
# 扩建不是新建
b
[1, 2, 3, 4, 5]
a
[1, 2, 3, 4, 5]
a=[1,2]
b=a
b=b+[4,5]
b
[1, 2, 4, 5]
a
[1, 2]
基本的不可变对象包括数字、字符串、布尔值(也算数字)以及元组;可变对象包括列表、集合、字典。
元组对象的“不可变性”,是指元组内部保存的各个地址号码不允许修改;但是这些号码所指向的内存单元中如果是可变对象(比如列表),那么这些可变对象仍可随意修改,与元组无关。
列表与循环
price=[100,220,310]
for i in price:
print(i)
for i in price:
i=i*7
print(price)
100
220
310
[100, 220, 310]
按上述写法,并不能修改列表元素
只是变化的i,不会变化price
要修改元素,最好直接用while语句
price=[100,220,310]
i=0
while i<len(price):
price[i]=price[i]+7
#直接改列表
i+=1
print(price)
import xlwings as xw
import random
app=xw.App()
wb=app.books.open('E:\拷贝过来的文件\全民一起玩Python\MyProject\皇帝寿命.xlsx')
names=wb.sheets['Sheet2'].range('A2:B23').value
wb.close()
app.quit()
def order(s):
return s[1]
names.sort(key=order,reverse=True)
#以order为函数排列
#循环打印
for n in names:
print(n)
random.shuffle(names)
#重新洗牌,随机生成序列
award=random.sample(names,2)
print(award)
#随机抽取几个
[‘弘历’, 87.43]
[‘玄烨’, 68.67]
[‘旻宁’, 67.49]
[‘朱棣’, 64.32]
[‘颙琰’, 59.84]
[‘朱厚熜’, 59.39]
[‘朱翊钧’, 56.99]
[‘胤禛’, 56.85]
[‘朱高炽’, 46.81]
[‘朱祐杬’, 43.0]
[‘朱见深’, 39.78]
[‘朱常洛’, 38.11]
[‘朱瞻’, 36.9]
[‘朱祁镇’, 36.26]
[‘朱载垕’, 35.36]
[‘朱祐樘’, 34.88]
[‘朱由检’, 33.24]
[‘奕詝’, 30.12]
[‘朱厚照’, 29.5]
[‘福临’, 22.91]
[‘朱由校’, 21.75]
[‘载淳’, 18.72]
[[‘朱高炽’, 46.81], [‘弘历’, 87.43]]
Process finished with exit code 0
对这个学历进行排序,并且保留修改之前的顺序
import xlwings as xw
import random
app=xw.App()
wb=app.books.open('E:\拷贝过来的文件\全民一起玩Python\MyProject\皇帝寿命.xlsx')
names=wb.sheets['Sheet3'].range('A2:B10').value
wb.close()
app.quit()
d={'初中':0,'高中':1,'本科':2,'硕士':3,'博士':4}
def degree_order(s):
t=s[1]
return d[t]
#用字典存储要比较的键值,然后以此为排序的函数
'''sort 是直接改了列表,没办法读回原来的值
#如果写b=names企图来备份,是不行的
#因为这里的b是指向的地址,names变,b指的位置还是要变'''
c=sorted(names,key=degree_order)
#sorted是不改变原来列表,直接创新表
#这样就可以实现了
#循环打印
for n in names:
print(n)
#print(b)
for n in c:
print(n)
或者写为
b=names.copy()
names.sort(key=degree_order)
#循环打印
print(b)
for n in names:
print(n)
题目一:三种读列表的方式
读列表
三种形式
a = [3,5,7,9]
for x in a:
print(x)
x = 0
while x<len(a):
print( a[x] )
x += 1
for x in range( len(a) ):
print( a[x] )
题目二:指定列表中所有元素乘指定倍数
请编写一个函数,能够将指定的列表中所有元素都乘以指定倍数。该函数接收两个参数:需要修改的列表、需要乘以的倍数。具体调用形式如下(假设该函数名字是 list_times ):
lst=[1,3,5,7]
def list_times(s,i):
for x in range(len(s)):
s[x]*=i
return s
list_times(lst,15)
print(lst)
题目三:按照《百家姓》顺序对该列表排序
《百家姓》的前八位顺序是“赵钱孙李周吴郑王”。假设现在有一个列表 ,其中是公司里多位员工的姓氏(该公司每位员工都是这八姓之一):
请编写一个排序函数,从而能够按照《百家姓》顺序对该列表排序。
names=[‘钱图’,‘李义’,‘吴天’,‘王力’,‘李新’,‘吴永’,‘赵清’,‘王刚’,‘王伍’,‘郑朵’,‘周青’,‘孙莲’,‘王义’,‘李宏’,‘孙月’,‘赵婷’,‘周显’ ]
names=['钱图','李义','吴天','王力','李新','吴永','赵清','王刚','王伍','郑朵','周青','孙莲','王义','李宏','孙月','赵婷','周显' ]
d={'赵':0,'钱':1,'孙':2,'李':3,'周':4,'吴':5,'郑':6,'王':7}
def degree_order(s):
t=s[0]
return d[t]
#用字典存储要比较的键值,然后以此为排序的函数
b=names.copy()
names.sort(key=degree_order,reverse=True)
#循环打印
print(b)
for n in names:
print(n)
题目四:按照员工姓氏排序
对表格中 B3:D657 范围内的全部员工记录,按照员工姓氏排序。
import xlwings as xw
app=xw.App()
wb=app.books.open('E:\拷贝过来的文件\全民一起玩Python\MyProject\第十二课作业.xlsx')
wb.sheets['Sheet3'].range('C3').value='Nihao'
names=wb.sheets['Sheet1'].range('B3:D657').value
d={'赵':0,'钱':1,'孙':2,'李':3,'周':4,'吴':5,'郑':6,'王':7}
def degree_order(s):
t=s[0][0]
return d[t]
#用字典存储要比较的键值,然后以此为排序的函数
names.sort(key=degree_order,reverse=False)
wb.sheets['Sheet1'].range('F3:H657').value=names
for n in names:
print(n)
wb.close()
app.quit()