一、Python简介
Python:Guido(龟叔)发明的,丹麦的。
Python解释器,和java虚拟机差不多。
人生苦短,我用Python。
Python:蟒蛇,源于作者喜欢的一部电视剧
优点:简单,易学,免费,开源,高层语言,可移植性,面向对象,可扩展性(可以在中间用C或C++编写),丰富的库
缺点:运行速度慢,国内市场小,中文资料匮乏,框架选择太多。
应用:
- web应用开发
- 操作系统管理,服务器运维的自动化脚本
- 科学计算
- 桌面软件:PyQt、PySide、wxPython、PyGTK是Python开发桌面应用程序的利器
- 服务器软件(网络软件)
- 游戏
二、Python基础知识
2.1注释:多行注释:'''........ ''',"""……."""。
2.2Python2中不能有中文,解决方法:在第一行加上
#coding=utf-8
或者
#-*- coding:utf-8 -*-(Python官方推荐)
2.3定义变量:直接写变量名,money=3 不需要说明类型。
2.4输入与输出
输入input:
height=input(“请输入你的升高:”)
input输入的默认是字符串类型,type(a),查看变量类型
输出print
使用print同时输出两个变量:
age=24 age2=25 print("age=%d,age2=%d"%(age,age2))print("")默认自动换行,print("\n")会换两行。
print("",end=""),就不换行了。
整型%d,字符串%s,和C一样。
2.5Python2和Python3区别
input时候的区别
#Python3中控制行测试 a=input("请输入你的名字") 请输入你的名字>? 1+4 a Out[3]: '1+4'
Python3中输入1+4,它会当成字符串,不会进行运算a="1+4"
Python2中输入1+4,它会进行计算,a=5
2.6Python基本数据类型
2.7if....else
age=input("pleat input your age:")#默认input是str类型 age_num=int(age)#转换为int类型,注意和C语言中区别 if age_num>18:#if后面一般不带括号,if后面的冒号 print("可以去网吧了") else:#注意else后面也有冒号 print("回家写作业吧")
if...elif
sex = input("请输入你的性别:") if sex=="男": print("你是男性") elif sex=="女": print("你是女性") elif sex=="中":#elif后面不一定要else,语法上是对的 print("你是中性")
C语言中也是一样。但是总觉得elif后面不更上else感觉很别扭,少了点什么。
if...if,if嵌套
ticket=1#1表示有车票,0表示没有车票 knifelength=18#cm if ticket==1: print("通过了车票的检查") if knifelength<=10: print("通过了安检,进入了候车厅") else: print("没有通过安检") else: print("兄弟,你还没买票了。")if里面一般只嵌套一个if,太多了程序就差劲。
2.8变量命名规则
和C中一样
2.9关键字
查看Python中关键字
import keyword keyword.kwlist
关键字 | 含义 |
---|---|
False |
布尔类型的值,表示假,与 True 相反 |
None |
None 比较特殊,表示什么也没有,它有自己的数据类型 - NoneType 。 |
True |
布尔类型的值,表示真,与 False 相反 |
and |
用于表达式运算,逻辑与操作 |
as |
用于类型转换 |
assert |
断言,用于判断变量或者条件表达式的值是否为真 |
break |
中断循环语句的执行 |
class |
用于定义类 |
continue |
跳出本次循环,继续执行下一次循环 |
def |
用于定义函数或方法 |
del |
删除变量或序列的值 |
elif |
条件语句,与 if 、else 结合使用 |
else |
条件语句,与 if 、elif 结合使用。也可用于异常和循环语句 |
except |
except 包含捕获异常后的操作代码块,与 try 、finally 结合使用 |
finally |
用于异常语句,出现异常后,始终要执行 finally 包含的代码块。与 try 、except 结合使用 |
for |
for 循环语句 |
from |
用于导入模块,与 import 结合使用 |
global |
定义全局变量 |
if |
条件语句,与 else 、elif 结合使用 |
import |
用于导入模块,与 from 结合使用 |
in |
判断变量是否在序列中 |
is |
判断变量是否为某个类的实例 |
lambda |
定义匿名函数 |
nonlocal |
用于标识外部作用域的变量 |
not |
用于表达式运算,逻辑非操作 |
or |
用于表达式运算,逻辑或操作 |
pass |
空的类、方法或函数的占位符 |
raise |
异常抛出操作 |
return |
用于从函数返回计算结果 |
try |
try 包含可能会出现异常的语句,与 except 、finally 结合使用 |
while |
while 循环语句 |
with |
简化 Python 的语句 |
yield |
用于从函数依次返回值 |
2.10运算符
a=5 b=2 a/b#2.5 a//b#2 2**10=1024#乘方 “H”*10=“HHHHHHHHHH”#乘以10次
三、流程控制
3.1逻辑运算符
3.1.1and,or
if..else中注意缩进问题。
age=int(input("请输入你的年龄:")) if (age>0) and (age<120): print("是正常年龄") else: print("不是正常年龄") #Python中不能随意缩进,否则会报unexpected indent错误。
3.1.2not
相当于C中的!
3.2while循环
Python中没有do..while,也没有switch。
i=1 while i<=10:#Python中不喜欢加括号,就不加吧。 print(i) i=i+1
while...while
#九九乘法表专用 i=1 while(i<=9): j=1 while(j<=i): print("%d*%d=%d\t"%(j,i,i*j),end="")#\t,久久乘法表专用 j+=1 print("") i+=1
3.3for循环
name = "laowang" for temp in name: print(temp,end="")
3.4break,continue
和C中一样
3.5随机数
import random random.randint(0,2)#生成0,1,2的随机整数
3.6复合运算符
i+=1, Python中没有i++,++i。
四、常见数据类型
4.1字符串
- 转换为字符串类型:str(x)
- 求字符串长度:len(x)
name="laowang" len(name)=7#不算\0
- 字符串的连接:“+”,格式化
a = "lao" b = "wang" #第一种连接方式 c = a +b #c="laowang" #第二种连接方式 d = "===%s==="%(a+b) #和格式化输出一样 print(c) print(d)
- 字符串中的下标,用中括号[ ]表示,
name=“laowang” name[0]#l name[-1]#g,从后往前取 name[-2]#n,倒数第二个 name[len(name)-1]#太麻烦
- 字符串切片name[start:end],name[start:end:step]
包括start,不包括end,注意步长在最后
name="laowang" name[0:2]#la name[0:-1]#laowan name[1:]#取到最后,包括最后,aowang name[0:-1:2]#loa,步长为2 #逆序 name[-1::-1]#从-1开始,向左取,步长为-1 name[::-1]#逆序,-1可以省略 #正序 name[::]
- 字符串常见操作
find | 查找字符串中是否有指定的字符串,如果有返回第一个找到的字符串的首字母下标,否则返回-1 |
rfind | 从右向前找,功能同find |
index | 查找到时find,查找不到时出现异常 |
rindex | 从右向前找,功能同index |
count | 统计子字符串出现的个数 eg:name="aaaa" name.count("aa") #2 |
replace | replace("str1","str2",n),把str1替换成str2,n为替换的次数,n省略时,默认全部替换。产生一个新字符串,原字符串不变 |
split | 切割字符串。作用:按照空格切割,统计单词个数 |
capitalize | 首字母大写 |
title | 字符串中每个单词的首字母都大写 |
lower | 所有字母转换为小写。作用:用户输入yes,YES,Yes时候,同意转换为yes,进行判断 |
upper | 所有小写字母转换为大写 |
startwith | startwith("obj"),判断字符串是否以"obj"开头,name=“wang XXXX” 判断是不是以“王”姓开头 |
endwith | endwith("obj"),判断文件格式时候用的多。file_name="xxxx.txt" file_name.endwith(".txt")#True |
center | center(n),居中对齐,补空格,n为总长度 |
ljust | 左对齐 |
rjust | 右对齐 |
strip |
删除字符串两边空字符串 |
lstrip | 删除字符串左边空字符串 |
rstrip | 删除字符串右边空字符串 |
partition | partition("obj"),按照obj进行分割,返回分割后的元组。从左向右,找到第一个截止 |
rpartition | 从右向左,功能同上 |
splitlines | 按照换行符分割,返回列表 |
isalpha | 判断字符串是不是都是字母 |
isdigit | 判断字符串是不是都是数字 |
isalnum | 判断字符串是不是都是由字母和数字组成的。作用:网站注册账号时,只能是字母和数字 |
isspace | 判断是不是都是空格 |
join | join(str),将序列中的元素以指定的字符连接生成一个新的字符串。 |
#split mystr="lao wang ni hao a " mystr.split(" ") Out[43]: ['lao', 'wang', 'ni', 'hao', 'a', '']
#partition mystr="lao wang ni hao a lao wang" mystr.partition("wang") Out[47]: ('lao ', 'wang', ' ni hao a lao wang')
#splitlines test="hello\nworld" test.splitlines() Out[49]: ['hello', 'world']
#join a=["aaa","bbb","ccc"] b=" " b.join(a) Out[52]: 'aaa bbb ccc'
#isdigit() a = "df" a.isdigit() Out[55]: False
列表连接成字符串
a = ["h","u","a","n","g"] "".join(a) Out[20]: 'huang'
面试题:
#删除字符串中的空格以及\t a="lao wang \t ni hao \t laowang" result = a.split() b = "".join(result) print(b)
4.2列表
和C不同,Python中列表可以包含不同类型
a=["d","Fsdf",111,3.24]
一般用来存储相同类型
#列表相加是列表合并 [100]+[100] Out[62]: [100, 100]
- 增
append() |
追加,没有返回值 |
insert() | 插入 |
extend() | 延伸,合并两个列表 |
names=["老王","老李","老张"] #追加 names.append("老赵") names.append("悟空") #插入 names.insert(0,"八戒") names.insert(2,"沙僧") print(names) names2=["huangyang","yuanmei","zhonglingqian"] #合并两个列表 names.extend(names2)#常用 result=names+names2#不常用,两个列表可以相加 print(names) print(result)
#append,extend小区别 a=[11,22,33,44] b=[55,66] a.extend(b) a Out[95]: [11, 22, 33, 44, 55, 66] a.append(b) a Out[97]: [11, 22, 33, 44, 55, 66, [55, 66]] a.extend(77)#报错,这里extend只能填可迭代的类型,不能直接添加一个数字。
- 删
pop | 删除最后一个元素,返回删除的那个元素 |
remove | 根据内容删除,没有返回值 |
del xxx[index] | 根据下标删除,没有返回值 |
names=["老王","老李","老张","老王","huangyang","yuanmei","zhonglingqian"] names.pop() Out[54]: 'zhonglingqian' names Out[55]: ['老王', '老李', '老张', '老王', 'huangyang', 'yuanmei'] names.remove("老王") names Out[57]: ['老李', '老张', '老王', 'huangyang', 'yuanmei']
列表切片还是列表
names=["老王","老李","老张","老王","huangyang","yuanmei","zhonglingqian"] names[0:2] Out[62]: ['老王', '老李']
- 改
names=["老王","老李","老张","老王","huangyang","yuanmei","zhonglingqian"] names[0]="老刘" names Out[65]: ['老刘', '老李', '老张', '老王', 'huangyang', 'yuanmei', 'zhonglingqian']
查
in | 在 if "老王" int names: |
not in | 不在 if "老黄" not in names: |
names=["老王","老李","老张","老王","huangyang","yuanmei","zhonglingqian"] if "老王" in names: print("老王在") 老王在 if "老黄" not in names: print("老黄不在") 老黄不在
#名字管理系统 #1.打印功能提示 print("="*50) print(" 名字关系系统 ") print("1:添加一个新的名字") print("2:删除一个名字") print("3:修改一个名字") print("4:查询一个名字") print("0:退出") print("="*50) names=[] while True: #2.获取用户输入的序号 num = int(input("请输入功能序号:")) if num==1: new_name=input("请输入名字:") names.append(new_name) elif num==2: pass elif num==3: pass elif num==4: find_name=input("请输入你要查找的名字:") if find_name in names: print("有") else: print("没有此人") elif num==0: break else: print("你的输入有误,请重新输入:")
列表解析
range(1,10) Out[18]: range(1, 10)
Python3中range生成的不是列表,Python2中生成的是列表,避免了range占用大的内存。
a = [i for i in range(1,8)] a Out[20]: [1, 2, 3, 4, 5, 6, 7]
b = [1 for i in range(1,8)] b Out[22]: [1, 1, 1, 1, 1, 1, 1]
c = [i for i in range(10) if i %2 ==0] c Out[27]: [0, 2, 4, 6, 8]
d = [i for i in range(3) for j in range(2)] d Out[29]: [0, 0, 1, 1, 2, 2]
e = [(i,j) for i in range(3) for j in range(2)] e Out[31]: [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
a = [2,3,4,5] b = [i if i%2==0 else 1 for i in a]#if在for前面的时候,必须紧跟着else b [2, 1, 4, 1]
a = [2,3,4,5] b = [i for i in a if i%2==0 else 1]#if在for后面的时候,后面不能跟着else b#报错
a = 1 b = 2 c = a if a>b else b c 2
4.3字典
infor={"name":"班长","addr":"山东","age":18} print("%s %d %s"%(infor["name"],infor["age"],infor["addr"]))
#名片管理系统 #1.打印功能提示 print("="*50) print(" 名片管理系统 ") print(" 1.添加一个新的名片:") print("2.删除一个名片:") print("3.修改一个名片") print("4.查询一个名片") print("5.显示所有的名片") print("6.退出") card_infor=[] while True: #获取用户的输入 num = int(input("请输入操作序号:")) #根据用户的输入进行操作 if num==1: new_name=input("请输入名字:") new_qq=input("请输入qq:") new_addr=input("请输入地址:") #定义一个字典,用来存储新的名片 new_dic={} new_dic["name"]=new_name new_dic["qq"]=new_qq new_dic["addr"]=new_addr #将字典添加到列表中 card_infor.append(new_dic) print(card_infor) elif num==2: pass elif num==3: pass elif num==4: find_name=input("请输入你要查找的名字:") flag=0#0:没有找到,1:找到了 for card in card_infor: if card["name"]==find_name: flag=1 print("找到了") break if flag==0: print("没有找到") elif num==5: print("姓名\tqq\t\t地址")#这里后面不知道为什么要加两个\t才能对齐 for card in card_infor: print("%s\t%s\t%s"%(card["name"],card["qq"],card["addr"])) elif num==6: break else: print("你的输入有误,请从新输入:")
增删查改
infor={"name":"laowang"} infor["age"]=18#增加 infor["qq"]=231321 infor Out[76]: {'age': 18, 'name': 'laowang', 'qq': 231321} infor["qq"]=11111#没有就增加,有就修改 infor Out[78]: {'age': 18, 'name': 'laowang', 'qq': 11111} del infor["qq"]#删除,没有就报错 infor Out[80]: {'age': 18, 'name': 'laowang'} infor.get("qq")#查询,没有返回None infor.get("age")#返回18
遍历
dic={"name":"huang","age":18} for key in dic.keys(): print(key)#列表 for value in dic.values(): print(value)#列表 for item in dic.items(): print(item)#元组 for a,b in dic.items(): print("key=%s,value=%s"%(a,b))
#拆包 a=(1,2) b,c=a a Out[109]: (1, 2) b Out[110]: 1
4.4while,for循环遍历列表
#for,简单 nums=[11,22,33,44,55] for num in nums: print(num)
#while,麻烦 nums=[11,22,33,44,55] nums_length=len(nums) i=0 while i < nums_length: print(nums[i]) i+=1
4.5for...else
for中break只要终止了for,else也一并跳过,不执行。nums=[11,22,33,44] for num in nums: print(num) else: # else在for循环执行完之后才执行,如果for循环里面有break,导致for循环没有执行完,else就不执行。 print("====")#此行执行
nums=[11,22,33,44] for num in nums: print(num) if num==22: break else: # else在for循环执行完之后才执行,如果for循环里面有break,导致for循环没有执行完,else就不执行。 print("====") #只输出11,22。此行不执行
for i in range(5): print(i) if i == 4: break else: print(100)#1,2,3,4
4.6元组
与列表类似,元组的元素不能修改,元组使用小括号
num=(11,22,33) type(num) Out[10]: tuple
五、函数
5.1定义函数
在文件中,可以在任意位置定义函数,但是一般都在开始定义函数,否则会被打的。
#定义函数 def print_menu(): print("menu") print_menu()
注意格式,def,后面有冒号,函数体要缩进。
#定义带有参数的函数:计算两个数的和 def sum(a,b): return a+b print(sum(1,2))
#返回多个参数时 def test(): a = 11 b = 12 c = 13 #return [a,b,c]#第一种 #return (a,b,c)#第二种 return a,b,c#第三种,其实和第二种一样。返回(a,b,c)a = test() a,b,c=test()#两种接收方法都可以
#不能直接定义空函数,最少也得有个pass。 def test(): pass def test(): #只有这个会报错。
5.2局部变量与全局变量
局部变量:函数内定义的,局部变量会屏蔽全局变量
全局变量:函数外定义的
#全局变量 def fun(): print("a=%d"%a) a=100 fun() #100
#局部变量与全局变量,函数内修改全局变量值注意点。 wendu = 0 def get_wendu(): #wendu = 33 #如果wendu这个变量已经在全局变量的位置定义了,这里wendu=33,有歧义,可以理解为修改全局wendu的值,也可以理解为定义一个局部变量wendu, # 所以为了消除这种歧义,Python中这里表示定义了一个局部变量。如果要修改全局变量的值,使用下面的方法。 global wendu #要表示使用的是全局变量需要这样写 wendu = 33 def print_wendu(): print("temperature is %d"%wendu) get_wendu() print_wendu()
- 全局变量定义位置说明
#全局变量定义位置说明 a = 100#可以 def test(): print("a=%d"%a) print("b=%d"%b) print("c=%d"%c) b = 200#可以 test() c=300#不可以,定义得放在函数调用之前。
编程时:先全局变量定义,再函数定义,把全局变量定义放到函数定义前面。
- 函数文档说明
#函数文档说明 def print_haha(): """这个函数的目的是print出haha""" print("haha") print_haha() #help(print_haha)
5.3缺省参数
函数的形参有一个默认值,带有默认值的参数一定要位于参数列表的最后面,可以有多个。
#缺省参数 def test(a,b=22,c=33):#缺省参数 print(a) print(b) print(c) test(11,22,c=44)
位置实参
关键字实参:只放放在位置实参后面
- 不定长参数
#不定长参数,求任意个数的和 def sum(a,b,*args):#最后一个参数写成*args的格式,多余的元素存在args中,args是一个元素,如果没哟多余的元素,args就是空元组 print(a) print(b) print(args) result = a +b for num in args: result += num print(result) sum(1,2,3,4,5)
#缺省实参与不定长实参 def test(a,b,c=33,*args): #缺省形参会被赋予值 print(a) print(b) print(c) print(args) test(1,2,3,4,5)#1,2,3,(4,5)
#完整的不定长参数 def test(a,b,c=33,*args,**kwargs):#args保存多余的没有变量名的变量,kwargs保存有名字的变量,以字典格式. print(a)#1 print(b)#2 print(c)#3 print(args)#(4,5) print(kwargs)#{'task': 99, 'done': 89} test(1,2,3,4,5,task=99,done=89)#1,2,3,(4,5),{'task': 99, 'done': 89}
- 拆包
#拆包 def test(a,b,c=33,*args,**kwargs):#args保存多余的没有变量名的变量,kwargs保存有名字的变量,以字典格式. print(a)#1 print(b)#2 print(c)#3 print(args)#(((4, 5, 6), {'name': 'laowang', 'age': 18}) print(kwargs)#{} A = (4,5,6) B = {"name":"laowang","age":18} test(1,2,3,A,B)
#拆包 def test(a,b,c=33,*args,**kwargs):#args保存多余的没有变量名的变量,kwargs保存有名字的变量,以字典格式.多余的位置实参,多余的关键字实参 print(a)#1 print(b)#2 print(c)#3 print(args)#(4, 5, 6) print(kwargs)#{{'name': 'laowang', 'age': 18} A = (4,5,6) B = {"name":"laowang","age":18} test(1,2,3,*A,**B) #拆包,*A对元组进行拆包,将元素拆成一个个元素;*B对字典进行拆包,将字典拆成一个个键值对。 print(*A),4,5,6 #print(**B)#直接输出会报错
- 引用
C语言中的复制都是引用
A = [11,22,33] B = A A.append(44) A Out[42]: [11, 22, 33, 44] B Out[43]: [11, 22, 33, 44]
a = 10 b = a#a,b指向同一个内存地址 a = 20#改变a的值,a指向了别的地方 b Out[47]: 10
- 不可变,可变类型
不可变:数值、字符串、元组
可变:列表、字典
a = "hello" id(a) Out[52]: 1714343478528 a = "world"#a指向了其他地方 id(a) Out[54]: 1714378747552 a[0] = "h"#会报错
数值,字符串,元组都可以当成字典的key。
列表和字典不能当key。
- 递归
#递归 def factorial(n): if n==0 or n==1: return 1 else: return factorial(n-1)*n print(factorial(10))
- 列表排序
nums= [2,3,5,1,10,5,8] nums.sort() nums Out[59]: [1, 2, 3, 5, 5, 8, 10] nums.sort(reverse=True)#从大到小 nums Out[61]: [10, 8, 5, 5, 3, 2, 1]
#列表元素为字典排序 list1 = [{"name":"laowang","age":18},{"name":"xiaoming","age":20},{"name":"banzhang","age":19}] #list1.sort()#列表中是数组进行排序时,函数内还得有参数,没参数会报错。 list1.sort(key=lambda x:x["name"]) print(list1)#[{'name': 'banzhang', 'age': 19}, {'name': 'laowang', 'age': 18}, {'name': 'xiaoming', 'age': 20}]
- 匿名函数
def test(a,b,func): result = func(a,b) return result num = test(11,22,lambda x,y:x+y) print(num)
#输入匿名函数 def test(a,b,func): result = func(a,b) return result func = eval(input("请输入一个匿名函数:"))#input输入为字符串,eval()去掉引号,将字符串转换为表达式 num = test(11,22,func) print(num)
- 交换两个变量的值
a = 5 b = 10 a = a + b b = a - b a = a -b print("a=%d,b=%d"%(a,b))
#交换两个变量的值 a = 5 b = 10 a,b = b,a #Python独有 print("a=%d,b=%d"%(a,b))
- num+=num与num=num+num区别
不可修改类型时结果一样,可修改类型时结果不一样。
#num+=num 与num = num+num区别 a = [100] def test(num): num += num#,num为可修改类型时,直接在原基础上该 print(num)#[100,100] test(a) print(a)#[100,100]
#num+=num 与num = num+num区别 a = [100] def test(num): num = num + num#指向了别的地方 print(num)#[100,100] test(a) print(a)#[100]
六、文件
r | 只读,文件必须存在 |
w | 只写,不存在则创建,已存在则覆盖 |
a | 不存在则创建,已存在则在末尾追加 |
rb | 以二进制格式打开,只读.... |
wb | 以二进制格式... |
ab | 以二进制格式... |
r+ | 可读可写... |
w+ | 可读可写... |
a+ | 可读可写... |
rb+ | |
rw+ | |
ra+ |
f = open("if_else.py","r",encoding="utf-8",)#打开文件,如果报解码错误,就加上encoding="utf-8",默认以只读"r"打开 print(f.read())#读文件,默认读取所有文件 #print(f.read(4))#读1个字符文件,指针自动后移 f.close()#关闭 f = open("test.py","w") f.write("haha")#写文件 f = open("test.py","r",encoding="utf-8") print(f.read()) f.close()
复制文件
#复制一个文件,将f复制到f1 f = open("if_else.py","r",encoding="utf-8") content = f.read() f1 = open("if_else_copy.py","w+",encoding="utf-8") f1.write(content) #print(f1.read())#这是f1指向了文件的末尾,直接输出为空 f.close() f1.close()
文件重命名小技巧
将huangyang.txt改为huangyang[附件].txt
file = "huangyang.txt" position = file.rfind(".") new_file = file[:position] + "[附件]"+file[position:] print(new_file)
readline()逐行读取文件,返回字符串
readlines()按行读取文件,一下子读取所有行,返回列表,列表中每一个元素是一个字符串。
大文件读取,一点一点读
#复制一个文件,将f复制到f1 f = open("if_else.py","r",encoding="utf-8") f1 = open("if_else_copy.py","w+",encoding="utf-8") while True: content = f.read(1024)#一点一点读 if len(content)==0: break f1.write(content) #print(f1.read())#这是f1指向了文件的末尾,直接输出为空 f.close() f1.close()
文件的定位读写
seek(a,b) | 第一个参数表示偏移量,第二个参数表示是文件的位置,0:从头开始;1:从当前位置开始,2:从尾开始 |
tell() | 返回当前指针位置 |
#文件的定位读写 f = open("test.py","r",encoding="utf-8") f.seek(3,0)#第一个参数表示偏移量,第二个参数表示是文件的位置,0:从头开始;1:从当前位置开始,2:从尾开始 print(f.readline()) print(f.tell())#获取当前指针的位置 f.seek(0,0)#指针指向文件第一个元素,下标为0 print(f.tell())
文件的相关操作
- 文件重命名
os模块中的rename()可以完成对文件的重命名操作
rename(需要修改的文件名,新的文件名)
- 删除文件
remove()
remove(待删除的文件名)
- 获取当前路径目录列表
listdir()
import os os.rename("testtest.txt","testhehe.txt")#重命名 os.remove("testhehe.txt")#删除 os.listdir()#获取当前路径目录列表
批量修改文件名
#批量修改文件名 import os folder_name = input("请输入要重命名的文件夹") file_names = os.listdir(folder_name) for name in file_names: print(name) old_file_name = folder_name + "/" + name new_file_name = folder_name + "/" +"[京东出品]" + name os.rename(old_file_name,new_file_name) file_names = os.listdir(folder_name) for name in file_names: print(name)上面是批量增加一个东西,如果要批量减少一个东西怎么写了?
七、面向对象
类
名称:类名
属性:一组数据
方法:允许进行操作的方法
例子:坦克类
类名:Tank
属性:重量、速度、材料。。。
方法:开炮,移动,转弯。。
class 类名:
#属性
#方法
定义类与对象
class Cat: #属性 #方法 def eat(self):#必须写上self print("猫在吃鱼") def introduce(self): print("%s的年龄是%d" % (tom.name, tom.age))#错误写法示例 #创建一个对象 tom = Cat() tom.eat() #给对象添加属性 tom.name="汤姆" tom.age=18 print("%s的年龄是%d"%(tom.name,tom.age)) #创建另一个对象 lanmao = Cat() lanmao.nam2="蓝猫" lanmao.age=10 lanmao.introduce()#这里是找得到tom的,tom是全局变量,找得到tom,就找得到tom.age。
class Cat: #属性 #方法 def eat(self):#必须写上self print("猫在吃鱼") def introduce(self):#self参数放在第一个,对象指向谁,self就指向谁 print("%s的年龄是%d"%(self.name, self.age)) #创建一个对象 tom = Cat() tom.eat() #给对象添加属性 tom.name="汤姆" tom.age=18 #print("%s的年龄是%d"%(tom.name,tom.age)) tom.introduce() #创建另一个对象 lanmao = Cat() lanmao.name="蓝猫" lanmao.age=10 lanmao.introduce()
__init__方法
创建对象流程:
1.创建一个对象,Python自动调用__init__方法 ,返回创建的对象的引用
__str__方法
print(object),打印对象时候自动调用
class Cat: #属性 #方法 def __init__(self,name,age): self.name = name#对象中自动添加name属性 self.age = age def __str__(self): return "%s的年龄是:%d"%(self.name,self.age) def eat(self):#必须写上self print("猫在吃鱼") def introduce(self):#self参数放在第一个,对象指向谁,self就指向谁 print("%s的年龄是%d"%(self.name, self.age)) #创建一个对象 tom = Cat("tom",18) tom.eat() tom.introduce() #创建另一个对象 lanmao = Cat("laomao",10) lanmao.introduce() print(tom)#直接打印对象时候,系统自动调用__str__方法。 print(lanmao)
隐藏(保护)对象属性
通过方法来修改对象的属性,而不是直接修改对象的属性。
好处:
dog=Dog()
dag.age=-10
可以在函数中进行一些判断,对不正确的设置进行处理。
#保护对象属性 class Dog: def set_age(self,new_age): if new_age>0 and new_age<120: self.age=new_age else: self.age=0 def get_age(self): return self.age #dog.age=10#不直接这样写 dog=Dog() dog.set_age(10)#要先set_age,再get_age,不然会说dog对象没有属性age print(dog.get_age())
私有属性
私有方法
#私有方法 class Dog: #私有方法 def __send_msg(self):#前面加两个下划线 print("正在发送短信") def send_msg(self,new_money): if new_money>10000: self.__send_msg() else: print("余额不足,请先充值,再发送短信.") dog = Dog() dog.send_msg(100)
__del__(self)方法
对象彻底消失时执行
class Dog(): def __del__(self):#程序结束之前,清空内存,所有对象都会调用这个方法。程序中,对象被删除后,会调用这个方法 print("英雄over") dog1=Dog() dog2=dog1#dog1和dog2指向同一个对象 del dog1 del dog2 print("========")
class Dog(): def __del__(self):#程序结束之前,清空内存,所有对象都会调用这个方法。程序中,对象被删除后,会调用这个方法 print("英雄over") dog1=Dog() dog2=dog1#dog1和dog2指向同一个对象 del dog1 print("========")
注意两个程序打印的顺序。
测量对象的引用个数
sys.getrefcount()函数,测量结果比实际多1。
import sys class T(): pass t1 = T() print(sys.getrefcount(t1))#2,比实际的多1 t2 = t1 print(sys.getrefcount(t1))#3
继承、重写、调用父类中被重写的方法
#继承 class Animal(): def eat(self): print("-----吃-----") def drink(self): print("-----喝-----") def sleep(self): print("-----睡-----") def run(self): print("-----跑-----") class Dog(Animal):#继承Animal类 def bark(self): print("-----汪汪叫----") class Cat(Animal): def catch(self): print("----抓老鼠------") class Xiaotq(Dog):#哮天犬 def fly(self): print("-----飞-------") def bark(self):#重写父类函数 print("----哮天犬专有叫声------") #调用被重写的父类的方法1 #Dog.bark(self)#这里要加self #方法2 super().bark() dog1 = Dog() cat1 = Cat() xiaotq1 = Xiaotq() dog1.eat() cat1.eat() xiaotq1.eat() xiaotq1.bark()#默认先在子类中寻找,子类中没有时,调用父类的
私有方法、私有属性在继承中的表现
class A(): def __init__(self): self.num1 = 100 self.__num2 = 200 def test1(self): print("-----test1-----") def __test2(self): print("-----test2-----") def test3(self): self.__test2() print(self.__num2) class B(A): def test4(self): self.__test2()#这里不能访问父类的私有方法 print(self.__num2)#这里不能访问父类的私有属性 b = B() b.test1() #b.test2()#私有方法不会被继承 print(b.num1) #print(b.__num2)#私有属性不会被继承 b.test3() b.test4()
如果调用的是继承的父类中的公有方法,可以在这个公有方法中访问父类中的私有属性和私有方法,
如果在子类中实现了一个公有方法,那么这个方法是不能够调用继承的父类中的私有方法和私有属性。
多继承
#多继承,一个子类继承自多个父类 class Base(object):#所有类都继承自object类 def test(self): print("base") class A(Base): def test1(self): print("test1") class B(Base): def test2(self): print("test2") class C(A,B):#多继承 pass c1 = C() c1.test1() c1.test2() c1.test()
多继承_调用顺序
#多继承调用顺序 class Base(object):#所有类都继承自object类 def test(self): print("base") class A(Base): def test(self): print("A") class B(Base): def test(self): print("B") class C(A,B):#多继承 def test(self): print("C") c1 = C() c1.test() print(C.__mro__)#查看类中方法调用的顺序,如果在某个类中找到了方法,就停止搜索。 #C3算法 #实际开发中,尽量不要在不同的类中定义相同的方法。
多态
#多态 class Dog(object): def print_self(self): print("大家好,我是XXXX") class Xiaotq(Dog): def print_self(self): print("hello everybody,我是你们的老大") def introduce(temp):#Python是弱类型语言,多态不明显 temp.print_self() dog1 = Dog() dog2 = Xiaotq() introduce(dog1) introduce(dog2)
类属性,实例属性
#类属性,实例属性 class Tool(object): #类属性 num = 0#每个对象都可以访问 #方法 def __init__(self,new_name): self.name = new_name#self.name:实例属性,相当于这个对象里面的全局变量,这个对象的所有方法都可以访问 age = 2#这里相当于定义了一个方法里面的局部变量age,只能在这个方法里面访问,不能在其他方法里面访问 #num += 1 Tool.num += 1#访问类属性格式:类名.属性名 tool1 = Tool("铁锹") tool2 = Tool("工兵铲") tool3 = Tool("水桶") print(Tool.num)
1、什么是类对象,实例对象
类对象:类名
实例对象:类创建的对象
类对象
所拥有的属性,它被所有类对象
的实例对象
所共有,在内存中只存在一个副本
公有类属性:
如果在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去修改, 会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且如果通过实例对象引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
class people(object): name = "tom" p = people() p.age = 18#相当于在实例对象中添加了一个实例变量age print(p.name) print(p.age)# print(people.name) print(people.age)#错误,实例属性,不能通过类对象调用
类方法,实例方法,静态方法
#类方法,实例方法,静态方法 class Game(object): #类属性 num = 0 #实例方法 def __init__(self): #实例属性 self.name = "老王" #类方法 @classmethod def add_num(cls): cls.num = 100 #静态方法 @staticmethod def print_menu():#不需要参数 print("---------") print(" 穿越火线V11.1 ") print("---------") game = Game() #Game.add_num()#可以通过类名和对象来调用类方法 game.add_num() print(Game.num) Game.print_menu()#可以通过类名和对象来访问静态方法 game.print_menu()
property:
以后再看吧。
设计类
#设计类 #设计一个现代的4s店 class CarStore(object):#店铺类 def order(self,car_type): if car_type == "索纳塔": return Suonata() elif car_type =="名图": return Mingtu() elif car_type == "ix35": return Ix35() class Car(object):#车类 def move(self): print("车在移动") def music(self): print("正在播放音乐") def stop(self): print("车在停止") class Suonata(Car): pass class Mingtu(Car): pass class Ix35(Car): pass car_store = CarStore() car = car_store.order("索纳塔") car.move() car.music() car.stop()
#设计类,使用函数解耦合 #设计一个现代的4s店 class CarStore(object):#店铺类 def order(self,car_type): return select_car_by_type(car_type) def select_car_by_type(car_type):#使用函数解两个类的耦合,两个类由两个不同的人开发,一个类改了之后,另一个类跟着变不好 if car_type == "索纳塔":#使用函数来解除两个类的耦合,这样函数和Car()类可以由一个人开发,CarStore()类由一个人开发。 return Suonata() elif car_type == "名图": return Mingtu() elif car_type == "ix35": return Ix35() class Car(object):#车类 def move(self): print("车在移动") def music(self): print("正在播放音乐") def stop(self): print("车在停止") class Suonata(Car): pass class Mingtu(Car): pass class Ix35(Car): pass car_store = CarStore() car = car_store.order("索纳塔") car.move() car.music() car.stop()
#使用类解耦 class CarStore(object):#店铺类 def __init__(self): self.factory = Factory() def order(self,car_type): return self.factory.select_car_by_type(car_type) class Factory(): def select_car_by_type(self,car_type): if car_type == "索纳塔": return Suonata() elif car_type == "名图": return Mingtu() elif car_type == "ix35": return Ix35() class Car(object):#车类 def move(self): print("车在移动") def music(self): print("正在播放音乐") def stop(self): print("车在停止") class Suonata(Car): pass class Mingtu(Car): pass class Ix35(Car): pass car_store = CarStore() car = car_store.order("索纳塔") car.move() car.music() car.stop()
__new__方法:创建对象
#__new__方法 class Dog(object): def __init__(self): print("----init方法----") def __del__(self): print("----del方法-----") def __str__(self): print("----str方法----") return "对象的描述信息" def __new__(cls):#自己重写了new方法后,就不能创建对象了,需要调用父类的new方法创建对象。 print(id(cls)) print("----new方法-----") return object.__new__(cls)#这里有返回值 print(id(Dog))#输出对象指向的地址 dog1 = Dog()#做了三件事情1.调用new方法创建对象2.调用__init__方法初始化,3返回对象的应用
创建单例对象
#创建单例对象,无论创建多少个对象,这些对象都指向同一块内存地址. class Dog(object): __instance = None#隐藏的类属性 def __new__(cls, *args, **kwargs): if cls.__instance == None: cls.__instance = object.__new__(cls) return cls.__instance else: return cls.__instance a = Dog() b = Dog() print(id(a)) print(id(b))
只初始化一次对象
class Dog(object): __instance = None def __new__(cls, name): if cls.__instance == None: cls.__instance = object.__new__(cls) return cls.__instance else: return cls.__instance def __init__(self,name): self.name = name a = Dog("旺财") print(id(a))#2618025477120 print(a.name)#旺财 b = Dog("哮天犬") print(id(b))#2618025477120 print(b.name)#哮天犬
#只初始化一次对象 class Dog(object): __instance = None __init__flag = 0 def __new__(cls, name): if cls.__instance == None: cls.__instance = object.__new__(cls) return cls.__instance else: return cls.__instance def __init__(self,name): if Dog.__init__flag == 0: self.name = name Dog.__init__flag = 1 a = Dog("旺财") print(id(a))#2618025477120 print(a.name)#旺财 b = Dog("哮天犬") print(id(b))#2618025477120 print(b.name)#旺财
八、异常处理
try:
print(num)
print("-------")
except 异常名:
print("捕获到异常后,进行的操作")
异常
#异常 try: open("xxx.txt") print(name) print("----1----") except NameError: print("变量未定义") except FileNotFoundError: print("文件不存在") print("----2----")
#try,except,else,finally try: open("xxx.txt") print(name) print("----1----") except (NameError,FileNotFoundError): #一个except捕获多个异常 print("变量未定义") print("文件不存在") except Exception as ret:#捕获所有异常 print("如果用了Exception,只要上面的except没有捕获到异常,这个except一定会执行") print(ret)#查看异常信息 else: print("没有异常执行的功能") finally: print("有没有异常都会执行") print("----2----")
异常的传递
#异常的传递,函数里面发生的异常会传递到调用函数的地方 def test1(): print("------test1-1-------") print(num) print("-----test1-2--------") def test2(): print("------test2-1--------") test1() print("------test2-2--------") def test3(): try: print("-----test3-1--------") test1() print("------test3-2--------") except Exception as result: print("捕获到了异常,信息是:%s"%result) print(result) test3() print("-----华丽的分割线-------") test2()
抛出自定义异常
#自定义异常 class ShortInputException(Exception): def __init__(self,length,atleast): self.length = length self.atleast = atleast def main(): try: s = input("请输入...") if len(s) < 3: raise ShortInputException(len(s),3)#抛出异常 except ShortInputException as result: print("ShortInputException:输入的长度是%d,长度至少是%d"%(result.length,result.atleast)) else: print("没有发生异常") main()
异常处理中抛出异常
class Test(object): def __init__(self,switch): self.switch = switch def calc(self,a,b): try: return a/b except Exception as result: if self.switch: print("捕获开启,已经捕获到了异常") else: raise a = Test(True) a.calc(11,0) print("-----华丽的分割线-------") a.switch = False a.calc(11,0)
if判断中"",None,0,[],{},()都为假
非空为真
if "a": print("真") 真
九、模块
模块其实就是一个.py文件
查看模块存放路径
import random random.__file__ Out[9]: 'E:\\python\\lib\\random.py'
自定义模块:
放在当前文件目录下,或者系统自带的模块路径下
#创建HY.py模块 def test(): print("hy")
#在其他文件中使用 import HY HY.test()
当使用HY模块时,Python会将HY模块文件转换成字节码.pyc文件,保存在当前文件路径,相当于一个缓存文件。
cpython-36:
c表示Python解释器是C语言写的
36表示Python3.6版本。
多种导入方式
import HY HY.test() from HY import test test() from HY import test,test1 from HY import *#尽量少用这种方法,可能存在覆盖问题 import HY as hy#起一个别名
导入模块时,默认会把导入的模块执行一遍
#HY模块 def test(): print("hy") def test1(): print("hy") test() test1() #module.py import HY#会自动指向HY模块中的test(),test1()
import HY HY.test() HY.test1()
__name__
直接运行这个模块时,__name__的值为"__main__"
当在其他.py文件中调用这个模块时,__name__的值为自己的名字利用__name__来进行测试
#HY模块 def test(): print("hy") def test1(): print("hy") if __name__ == "__main__":#测试时执行,调用时不执行 test() test1() #module.py,调用模块 import HY HY.test() HY.test1()
__all__
控制模块中哪些东西可以被调用者使用
__all__ = ["test1","Test"]#__all__是一个列表,只有这里写的,才能在调用模块中使用 def test(): print("hy") def test1(): print("hy") num = 100 class Test(object): pass module.py中调用 from HY import * #test()#不能使用 test1() module.py中调用 import HY HY.test()#这种方法可以调用 HY.test1()
包
例:建立了两个模块recvmsg.py,sendmsg.py,把他们放到同一个文件夹TestMsg下,这个文件夹就是一个包。只不过现在还不能直接用recvmsg,sendmsg这两个模块。需要在TestMsg文件夹下面新建立__init__.py文件,在__init__.py文件中通过__all__变量来指明哪些模块可以被使用。
如果不建立__init__.py文件的话,可以导入import TestMsg成功,但是不能访问它下面的模块。
#recemsg.py def test1(): print("recvmsg--test1")
#sendmsg.py def test2(): print("send--test2")
#__init__.py __all__ = ["recvmsg"]
#testmsg.py from TestMsg import * recvmsg.test1() #sendmsg.test2()#不能访问
import TestMsg#这种导入方法不行,会把TestMsg当成模块, TestMsg.recvmsg.test1()#这里会报错,说TestMsg模块中没有recemsg
解决方法
#__init__.py __all__ = ["recvmsg"] from . import recvmsg #从当前路径下导入revemsg
#testmsg.py import TestMsg TestMsg.recvmsg.test1()#这时就可以访问了
在导入TestMsg时,会自动把__init__.py执行一遍
模块的发布,安装
给程序传递参数
#给程序传递参数 import sys print(sys.argv)#argv是一个列表,默认是程序名#['E:/TensorFlow/Python/Python_Learn/Python_Foundation/program_argv.py', '老王'] print("热烈欢迎%s的到来"%sys.argv[1])#热烈欢迎老王的到来pycharm中通过run->Edit Configurations->Script parameters来给程序传递参数
集合,元组,列表
a = (11,22,33,11,22,33) a Out[3]: (11, 22, 33, 11, 22, 33) b = [11,22,33,11,22,33] b Out[5]: [11, 22, 33, 11, 22, 33] c = {11,22,33,11,22,33} c Out[7]: {11, 22, 33}#集合set,没有重复元素
列表去重
a = [11,22,33,44,11,22,33] a = list(set(a))#通过集合去重 a Out[11]: [33, 11, 44, 22]
模块重新导入
查看模块导入的路径
import sys sys.path Out[13]: ['E:\\PyCharm 2017.2.3\\helpers\\pydev', 'E:\\PyCharm 2017.2.3\\helpers\\pydev', 'E:\\python\\python36.zip', 'E:\\python\\DLLs', 'E:\\python\\lib', 'E:\\python', 'E:\\python\\lib\\site-packages', 'E:\\python\\lib\\site-packages\\IPython\\extensions', 'E:\\TensorFlow\\Python\\Python_Learn\\Python_Foundation', 'E:/TensorFlow/Python/Python_Learn/Python_Foundation']sys.path是一个列表,可以自己修改。更改后查找的路径就变了。
#test.py def test(): print("------1----") print("------2----")
#_reload.py import test test.test()感觉不用reload呀,test.py中的内容改变后,reload.py中会自动更新。
模块循环导入问题
我导入你,你导入我,会报错
a.py from b import b def a(): print("--a--") b() a()
b.py from a import a def b(): print("--b--") def c(): print("--c--") a() c()上面在a中导入b,在b中导入a,会报错。
== 和 is
==判断值是不是一样
is判断是不是指向同一个内容
a = [1,2,3] b = [1,2,3] a == b Out[17]: True a is b Out[18]: False c = b c is b Out[20]: True id(a) Out[21]: 2367509601160 id(b) Out[22]: 2367509599944 id(c) Out[23]: 2367509599944
#注意点,有点意思。在某个整数范围内 a is b是真的 a = 100 b = 100 a is b Out[28]: True a = 10000 b = 10000 a is b Out[31]: False
深拷贝,浅拷贝
深拷贝:复制一份
浅拷贝:指向同一个地方
#浅拷贝 a = [11,22,33] b = a id(a) Out[34]: 2367509628552 id(b) Out[35]: 2367509628552
#深拷贝 import copy a = [11,22,33] c = copy.deepcopy(a) id(a) Out[39]: 2367509629896 id(c) Out[40]: 2367509628680
b = [44,55,66] c = [a,b] c Out[5]: [[11, 22, 33], [44, 55, 66]]
a = [11,22,33] b = [44,55,66] c = [a,b] c Out[5]: [[11, 22, 33], [44, 55, 66]] import copy e = copy.deepcopy(c) e[0] Out[9]: [11, 22, 33]
#copy.copy a = [1,2,3] b = [4,5,6] c = [a,b] import copy e = copy.copy(c) a.append(4) c[0] Out[8]: [1, 2, 3, 4] e[0] Out[9]: [1, 2, 3, 4] id(c) Out[10]: 2819516398984 id(e) Out[11]: 2819516564040
#元组与copy.copy a = [1,2,3] b = [4,5,6] c = (a,b) import copy e = copy.copy(c) id(c) Out[7]: 2480767999880 id(e) Out[8]: 2480767999880 a.append(4) a Out[10]: [1, 2, 3, 4] c[0] Out[11]: [1, 2, 3, 4] e[0] Out[12]: [1, 2, 3, 4]
进制
位运算
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| | 按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1 | (a | b) 输出结果 61 ,二进制解释: 0011 1101 |
^ | 按位异或运算符:当两对应的二进位相异时,结果为1 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
~ | 按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1 | (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。 |
<< | 左移动运算符:运算数的各二进位全部左移若干位,由”<<”右边的数指定移动的位数,高位丢弃,低位补0 | a << 2 输出结果 240 ,二进制解释: 1111 0000 |
>> | 右移动运算符:把”>>”左边的运算数的各二进位全部右移若干位,”>>”右边的数指定移动的位数 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
# -*- coding: UTF-8 -*-
a = 60 # 60 = 0011 1100
b = 13 # 13 = 0000 1101
c = 0
c = a & b; # 12 = 0000 1100
print "1 - c 的值为:", c
c = a | b; # 61 = 0011 1101
print "2 - c 的值为:", c
c = a ^ b; # 49 = 0011 0001
print "3 - c 的值为:", c
c = ~a; # -61 = 1100 0011
print "4 - c 的值为:", c
c = a << 2; # 240 = 1111 0000
print "5 - c 的值为:", c
c = a >> 2; # 15 = 0000 1111
print "6 - c 的值为:", c
输出:
1 - c 的值为: 12
2 - c 的值为: 61
3 - c 的值为: 49
4 - c 的值为: -61
5 - c 的值为: 240
6 - c 的值为: 15
~9 Out[20]: -10
私有化
xx:公有变量
_x:单前置下划线,from module import *时无法访问(一个以上_),当时 import modue时可以访问。
__xx:类里面定义私有化方法或属性
__xx__
#_private.py name1 = 100 _name2 = 200 __name3 = 300 from _private import * name1 Out[3]: 100 _name2 NameError: name '_name2' is not defined __name3 NameError: name '_name3' is not defined
为什么定义成私有属性之后在类外就无法访问了?
Python通过名字重整会将定义的私有属性改写为_类名+属性名
class Dog(): def __init__(self): self.__age = 10 dog = Dog() print(dog._Dog__age)#10
迭代器
可迭代对象:
一类是list,tuple,dict,set,str等
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable
判断是否可迭代
可以使用isinstance()判断一个对象是否是Iterable对象
from collections import Iterable isinstance([],Iterable) Out[4]: True isinstance({},Iterable) Out[5]: True isinstance("abc",Iterable) Out[6]: True isinstance(100,Iterable) Out[7]: False
迭代器
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
可以使用isinstance()判断一个对象是否是Iterator对象
from collections import Iterator isinstance([],Iterator) Out[9]: False isinstance((x for x in range(10)),Iterator) Out[10]: True
iter()函数
生成器都是Iterator对象,但list,dict,str虽然是Iterable,而不是Iterator对象。
把list,dict,str等Iterable编程Iterator可以使用iter()函数
a = [1,2,3,4] type(a) Out[12]: list iter(a) Out[13]: <list_iterator at 0x1a36f5dc5c0> b = iter(a) type(b) Out[15]: list_iterator next(b) Out[16]: 1 next(b) Out[17]: 2
闭包
def test(): print("-----1----") test Out[19]: <function __main__.test> b = test b() -----1---- b Out[22]: <function __main__.test>
定义:
在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的变量成为闭包。
def test(number): print("------1-----") def test_in(): print("-----2-----") print(number+100) print("-----3-----") return test_in test(100)() #输出 ------1----- -----3----- -----2----- 200
test函数在运行结束后,没有销毁,因为里面的test_in函数还要使用。
闭包运用
''' #闭包 def test(number): print("------1-----") def test_in(): print("-----2-----") print(number+100) print("-----3-----") return test_in test(100)() ''' #闭包运用,计算y=a*x+b的值,调用的时候只需要穿x的值,不需要传递a,b,x的值 def test(a,b): def test_in(x): print(a*x+b) return test_in line1 = test(1,1) line1(0)#1 line2 = test(10,4) line2(0)#4
装饰器
装饰器是程序开发中经常用到的一个功能,用好了装饰器,开发效率如虎添翼,是Python中必问的问题。装饰器是程序开发的基础知识,这个都不会,别跟别人说你会Python。
#函数重定义 def test(): print("--1--") def test():#有提示,但不报错 print("--2--") test()#2
装饰器距离
A开发的代码需要供其他人使用,现在需要加一个权限认证,需要A对自己开发的代码进行更改,调用方调用方式不改。
#开始,A的代码 def f1(): print("---f1---") def f2(): print("---f2---")
#调用方 f1() f2()
现在需要加权限认证,但是尽量不要对f1,f2函数内部的代码进行更改。
#初级更改 def w1(func): def inner(): print("----正在验证权限----") func() return inner def f1(): print("---f1---") def f2(): print("---f2---") f1 = w1(f1) f1()
使用装饰器方法
def w1(func): def inner(): print("----正在验证权限----") func() return inner #f1 = w1(f1) @w1#装饰器 def f1(): print("---f1---") @w1 def f2(): print("---f2---") f1()#有装饰器时,先默认运行f1 = w1(f1)
@w1内部执行的操作
执行w1函数,并将@w1下面的函数作为w1函数的参数
将执行完的w1函数返回值赋值给@w1下面的函数的函数名。
两个装饰器
#两个装饰器,将字体加粗,变斜体 def makeBold(fn): def wrapped(): print("---1---") return "<b>" + fn() + "<b/>" return wrapped def makeItalic(fn): def wrapped(): print("---2---") return "<i>" + fn() + "</i>" return wrapped @makeBold#后执行 @makeItalic#先执行 def test3(): print("---3---") return "hello world" ret = test3() print(ret)
#结果 ---1--- ---2--- ---3--- <b><i>hello world</i><b/>
装饰器什么时候进行装饰
example1:
#装饰器执行时间 def w1(func): print("---正在装饰---") def inner(): print("---正在验证权限---") func() return inner #这里不要加() @w1 #只要Python解释器执行到了这个代码,那么就会自动的进行装饰,而不是等到调用的时候才装饰 def f1(): print("---f1---") #在调用f1之前,已经进行装饰了 f1()example2:
def w1(func): print("---正在装饰1---") def inner(): print("---正在验证权限1---") func() return inner def w2(func): print("---正在装饰2---") def inner(): print("---正在验证权限2---") func() return inner @w1# f1 = w1(f1),后执行 @w2 # f1 = w2(f1),先执行 def f1(): print("---f1---") f1()
#结果 ---正在装饰2--- ---正在装饰1--- ---正在验证权限1--- ---正在验证权限2--- ---f1---
使用装饰器对有参数的函数进行装饰
def func(functionName): print("---func---1---") def func_in(a,b):#注意这里写法 print("---func_in---1---") functionName(a,b)#注意这里写法 print("---func_in---2---") print("---func---2---") return func_in @func def test(a,b): print("---test-a=%d,b=%d---"%(a,b)) test(11,22)
#使用装饰器对可变长参数函数进行装饰 def func(functionName): print("---func---1---") def func_in(*args,**kwargs):#注意这里写法 print("---func_in---1---") functionName(*args,**kwargs)#注意这里写法 print("---func_in---2---") print("---func---2---") return func_in @func def test(a,b): print("---test-a=%d,b=%d---"%(a,b)) test(11,22)