自定义函数def
一、数字类型
数字、字符串、字典、列表、元组、集合、队列、有序字典、默认字典等
二、初始函数
1、分类
1.1、自定义函数
1.2、内置函数
2、面向过程编程
1.1、定义:从上到下按照逻辑一点点写,遇到重复的功能,进行复制粘贴
1.2、缺点
代码量多,可读性差
代码重用性差
3、函数式编程
3.1、普通处理(while True 功能)--报警功能重复
while True: if cpu利用率 > 90 %: # 发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 硬盘使用空间 > 90 %: # 发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 内存占用 > 80 %: # 发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接
3.2、函数式编程
声明函数:用名字带指,增强重用性
将重复的操作放在前面,并且跟定义变量一样,定义相同的操作为一个变量,再进行调用
变量名带指的东西:字符串、列表、元组
发送邮件 # 发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90 %: 发邮件 if 硬盘使用空间 > 90 %: 发邮件 if 内存占用 > 80 %: 发邮件
4、声明变量
python的解释器将代码从上到下执行,先声明变量,将变量存储到内存当中-再使用变量
name = 'tang' #声明变量 print(name) #使用变量
5、声明函数
python解释器将代码从上到下执行,一旦遇到def函数就表示要创建一个函数,函数里面的内容就是下图中的pass
def h1(): #def:关键字 函数名:h1 pass #函数的内容
6、函数的内存存储结构
6.1、定义一个函数
def(关键字,解释器一旦遇到的话就表示要创建函数)
6.2、函数名
h1
6.3、扣号
固定搭配
6.4、函数体
将一个功能都放在一块,以后调用的时候执行这个功能
具体函数做了什么操作
6.5、返回值
7、发送邮件的函数举例
7.1、相关代码
def sendmail(): import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) msg['To'] = formataddr(["走人", '424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail('wptawy@126.com', ['424662508@qq.com', ], msg.as_string()) server.quit()
7.2、图解
7.3、结构解析
函数内容里面的代码(函数体)是不执行的,只有在调用的时候才会执行。
函数内容只是存储到内存当中而已。
8、调用函数(执行函数):当调用函数的时候,函数内容的代码就会一句一句进行执行
8.1、执行顺序
如下代码,执行顺序如下:1-17-3~15-19(数字代表代码中的行数)
1 def sendmail(): 2 3 import smtplib 4 from email.mime.text import MIMEText 5 from email.utils import formataddr 6 7 msg = MIMEText('邮件内容', 'plain', 'utf-8') 8 msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) 9 msg['To'] = formataddr(["走人", '424662508@qq.com']) 10 msg['Subject'] = "主题" 11 12 server = smtplib.SMTP("smtp.126.com", 25) 13 server.login("wptawy@126.com", "邮箱密码") 14 server.sendmail('wptawy@126.com', ['424662508@qq.com', ], msg.as_string()) 15 server.quit() 16 17 sendmail() #调用函数 18 19 print(123444)
9、断点
作用:可以很方便的知道程序执行到哪一句
利用pycharm先在代码面前打断点
利用debug模式进行调试
执行第一个断点的时候会暂停执行,再次点击运行按钮的时候才会执行
debug模式:没有打断点的函数不会执行
10、备注点
10.1、python语言执行顺序
python语言程序是从上往下执行代码的
其他语言(C、java):将整个文件放在内存里面,执行的时候直接调用内存的文件即可
10.2、相关代码
sendmail() #不能将调用函数放在上面,python程序都是从上往下执行程序的 def sendmail(): import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) msg['To'] = formataddr(["走人", '424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail('wptawy@126.com', ['424662508@qq.com', ], msg.as_string()) server.quit() print(123444)
三、返回值
1、定义
发送邮件的时候密码错误-邮件发送不成功
返回值:告知调用的人,邮件密码错误,发送是否成功
调用的时候接收返回值
return的也可以是字符串
def sendmail(): try: import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) msg['To'] = formataddr(["走人", '424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail('wptawy@126.com', ['424662508@qq.com', ], msg.as_string()) server.quit() except: return False #如果发送失败,执行这个代码 else: return True #如果执行成功,执行这个代码 ret = sendmail() #调用函数 print(ret) #等于上面return的值赋值给sendmail() if ret == True: print("成功啦") else: print("哎呀,失败啦。") #结果 #False #哎呀,失败啦。 #return的值也可以是字符串 def sendmail(): try: import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) msg['To'] = formataddr(["走人", '424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail('wptawy@126.com', ['424662508@qq.com', ], msg.as_string()) server.quit() except: return "ss" #如果发送失败,执行这个代码 else: return 'cc' #如果执行成功,执行这个代码 ret = sendmail() #调用函数 print(ret) #等于上面return的值赋值给sendmail() if ret == True: print("cc") else: print("ss") #结果: #ss #ss
2、停止
在函数中,一旦执行return的话,函数执行过程立即终止
执行顺序:1-6(h)-2-3-6(h1())-7
如果一个函数里面没有return的话,python里面会有一个默认的返回值:none
def h1(): print(123) return '111' #在函数中,一旦执行return的话,函数执行过程立即终止 print(456) h = h1() print(h) #结果 #123 #111 #没有return def h2(): print(123) h = h2() print(h) #结果 #123 #none
四、函数之基本参数
1、多个收件人
1.1、方法一
将全部的发邮件代码复制一遍,函数名修改成sendmail2即可--重复的比较多
def sendmail(): try: import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) msg['To'] = formataddr(["走人", '424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail('wptawy@126.com', ['1111@qq.com', ], msg.as_string()) server.quit() except: return "ss" #如果发送失败,执行这个代码 else: return 'cc' #如果执行成功,执行这个代码 ret = sendmail() #调用函数 print(ret) #等于上面return的值赋值给sendmail() if ret == True: print("cc") else: print("ss") def sendmail2(): try: import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) msg['To'] = formataddr(["走人", '424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail2('wptawy@126.com', ['2222@qq.com', ], msg.as_string()) server.quit() except: return "ss" #如果发送失败,执行这个代码 else: return 'cc' #如果执行成功,执行这个代码 ret = sendmail2() #调用函数 print(ret) #等于上面return的值赋值给sendmail() if ret == True: print("cc") else: print("ss")
1.2、方法二
两个函数不同的地方只有收件人
将这块不同的地方提取出来定义为一个变量,后面再去调用
def sendmail(haha): try: import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) msg['To'] = formataddr(["走人", '424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail('wptawy@126.com', [haha, ], msg.as_string()) server.quit() except: return "ss" #如果发送失败,执行这个代码 else: return 'cc' #如果执行成功,执行这个代码 ret = sendmail('name1') #调用函数
ret = sendmail('name2')
ret = sendmail('name3')
print(ret) #等于上面return的值赋值给sendmail() if ret == True: print("cc") else: print("ss")
2、形式参数:传什么就变成什么,类似上面的haha
3、实际参数:name1、name2、name3等传入的参数
3.1、定义
括号()相当于一个容器,传的实际参数(name1、name2等),将传的值name1赋值给haha,在代码块里面都可以被使用。
3.2、执行步骤
3.3、while True循环操作
让用户输入邮箱地址,将邮箱地址传给haha,将返回值返回给result,进行判断发送是否成功。
def sendmail(haha): try: import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐", 'wptawy@126.com']) msg['To'] = formataddr(["走人", '424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail('wptawy@126.com', [haha, ], msg.as_string()) server.quit() except: return "ss" #如果发送失败,执行这个代码 else: return 'cc' #如果执行成功,执行这个代码 while True: em = input('请输入邮箱地址:') result = sendmail(em) if result == 'cc': print('发送成功') else: print('发送失败') #结果 #请输入邮箱地址:24749 #发送失败 #请输入邮箱地址:
4、多个形式参数
4.1、默认上面接收几个参数,就应该传几个参数
def send (haha,content): print('发送邮件成功',haha,content) return True while True: em = input('请输入邮箱地址:') result = send(em,'meimei') if result == True: print('发送成功') else: print('发送失败') #结果 #请输入邮箱地址:1234 #发送邮件成功 1234 meimei #发送成功 #请输入邮箱地址:
4.2、形式参数与实际参数的对应关系
4.2.1、普通参数:一一对应
def send (aaa,bbb,ccc): print(aaa,bbb,ccc) print('发送邮件成功',aaa,bbb,ccc) return True while True: em = input('请输入邮箱地址:') result = send(111,'haha','hehe') if result == True: print('发送成功') else: print('发送失败') #结果 #请输入邮箱地址:tang #111 haha hehe #发送邮件成功 111 haha hehe #发送成功 #111对应aaa haha对应bbb hehe对应ccc
4.2.2、默认参数
如果传入的是两个参数的话,ccc等于是默认的ok
如果传入的是三个参数的话,取的是传入的参数,而不是默认的参数
python规定:如果要给参数设置默认参数的话,这个默认参数需要放到后面,不然会报错;如果多个默认参数的话,需要将多个默认参数全部放到后面
def send (aaa,bbb,ccc='ok'): print(aaa,bbb,ccc) print('发送邮件成功',aaa,bbb,ccc) return True while True: em = input('请输入邮箱地址:') result = send(111,'haha') if result == True: print('发送成功') else: print('发送失败') #结果 #请输入邮箱地址:tang #111 haha ok #发送邮件成功 111 haha ok #发送成功 #111对应aaa haha对应bbb hehe默认是ok
4.2.3、指定参数
def send (aaa,bbb): print(aaa,bbb) return True send('tang','mei') #默认参数 send(bbb='mei',aaa='tang') #指定参数 #结果 #tang mei #tang mei
五、动态参数
1、*号(args:元组类型):接收任意个实际参数
传100个参数
动态参数:不管传多少个实际参数,形式参数只需要写一个*号就好了,在形式参数前面加一个*号就会接收任意个数的实际参数
一个*号的话,一般都是用的args来作为函数名(具体可以查看)
args:元组类型
def h1(*args): print(args) print(type(args)) h1(11,22,'dsf','eqrsad') #结果 #(11, 22, 'dsf', 'eqrsad') #<class 'tuple'> 元组类型
传的是列表
上传的是列表的话,会讲列表当做是一个元素,传到args元组里面
def h1(*args): #args = (11) #args = ([11,22,'dw','dqw'],23) print(args,type(args)) h1(11) li = [11,22,'dw','dqw'] h1(li ,'23') #结果 #(11,) <class 'tuple'> #([11, 22, 'dw', 'dqw'], '23') <class 'tuple'> #将列表[11, 22, 'dw', 'dqw']当做一个元素直接传到h1里面
传特殊参数
内部做一个for循环,分成所有的函数传到元组里面
def h1(*args): print(args,type(args)) li = [11,22,'dw','dqw'] h1(li ) #将列表当成一个元素穿到元组里面 h1(*li) #将列表里面的元素拆分成单个传到元组里面 #结果 #([11, 22, 'dw', 'dqw'],) <class 'tuple'> #(11, 22, 'dw', 'dqw') <class 'tuple'> #特殊循环字符串 def h1(*args): print(args,type(args)) li = 'wuli' h1(*li ) #将列表里面的元素拆分成单个传到元组里面 #结果 #('w', 'u', 'l', 'i') <class 'tuple'>
2、**(kwargs:字典类型)
如下代码中,n1 = 'tang'为指定参数,**为字典类型,需要有key:value对
#正确 def f1(**kwargs): print(kwargs, type(kwargs)) f1(n1 = 'tang') #结果 #{'n1': 'tang'} <class 'dict'> #ni类似于key tang类似于value #错误 def f1(**kwargs): print(kwargs, type(kwargs)) f1('tang') # 结果 # 报错:TypeError: f1() takes 0 positional arguments but 1 was given # 因为**是属于字典类型,需要key:value对才可以,不然会报错
字典里面传字典
如果形式参数里面有**,传的参数也有**的话,就等于直接赋值
#字典嵌套字典 def f1(**kwargs): print(kwargs, type(kwargs)) f1(n1 = 'tang') dic = {'n2':'tang2','n3':3} f1(kk = dic) f1(**dic) #结果 #{'n1': 'tang'} <class 'dict'> #{'kk': {'n2': 'tang2', 'n3': 3}} <class 'dict'> 将kk全部代表key,{'n2': 'tang2', 'n3': 3}当成一个元素放到字典里面 #{'n3': 3, 'n2': 'tang2'} <class 'dict'> 在实际参数前面加**的话表示得是将dic字典里面的元素拆开来
3、总结
*:默认将传入的参数,全部放置在一个元组中,让函数去调用 f1(*{'n2':'tang2','n3':3})
**:默认将传入的参数,全部放置在一个字典中,让函数去调用 f1(**{'n2':'tang2','n3':3})
4、万能参数
不能将*放在后面,**放在前面,不然会报错
def f1(*args,**kwargs): print(kwargs, type(kwargs)) print(args, type(args)) f1(11,22,33,44,n1 = 'aa',n2 = 'bb') #结果 #{'n2': 'bb', 'n1': 'aa'} <class 'dict'> #(11, 22, 33, 44) <class 'tuple'> #会自动的识别是元组还是字典类型,分别自动封装 def f1(**kwargs,*args): print(kwargs, type(kwargs)) print(args, type(args)) f1(11,22,33,44,n1 = 'aa',n2 = 'bb') #结果 #SyntaxError: invalid syntax #不能将**放在前面*放在后面
六、利用动态参数实现format功能
1、format函数(格式化)
1.1、python自带的函数
格式化
%s、%d字符串格式化输出
format格式化输出
1.2、作用
格式化函数,用来格式化输出
p = 'i am {0},age{1}'.format('tang',20) print(p) #结果 #i am tang,age20 #0、1为占位符,format为传参数 #错误 p = 'i am {0},age{2}'.format('tang',20) print(p) #结果 #IndexError: tuple index out of range #占位符要按照顺序,不能错开,不然会报错
1.3、传参放到一个列表里面,列表会被当做一个元素--如果是加*号的话就会将元素分离
p = 'i am {0},age{1}'.format('tang',20) print(p) q = 'i am {0},age{1}'.format(*['tang',20]) print(q) #结果 #i am tang,age20 #i am tang,age20 #0、1为占位符,format为传参数
1.4、字典方式
如果传的参数有一个为name,传的值一定要有name = ‘xxx’
p = 'i am {name},age{age}'.format(name = 'tang',age=20) print(p) dic = {'name':'tang','age':20} s = 'i am {name}, age{age}'.format(**dic) print(s) #结果 #i am tang,age20 #i am tang,age20 #0、1为占位符,format为传参数
七、执行顺序
1)python代码的执行是由上往下一步一步执行的,先执行到a1+a2这一步,并且存储到内存当中
2)在执行a1*a2,并且将a1*a2存储到内存当中
3)python里面有一套自己的垃圾回收机制,定时去查找那些没人使用的垃圾并且清除掉。
4)所以最后执行的就是a1*a1这步操作,并且返回给ret
5)顺序:1(将函数存储到内存)-5(将函数存储到内存)-9(a1=8 a2 =8)-6(执行a1*a2操作)-9(将64返回给ret)-10(代表行号)
1 def f1 (a1,a2): 2 return a1+a2 3 4 5 def f1(a1,a2): 6 return a1*a2 7 8 9 ret = f1(8,8) 10 print(ret) 11 12 13 #结果 14 #64
八、函数传递参数(列表)
python函数传递参数的时候,传的值事重新复制一份呢?还是直接引用?
def f1 (a1): a1.append(999) li = [11,22,33,44] f1(li) print(li) #结果 #[11, 22, 33, 44, 999]
1、重新复制一份
a1直接重新复制一份li,在执行后面的操作,这样的话不会影响到li。
2、直接引用(正解)
直接改变li的值
九、作用域
1、局部变量
1.1、定义
自己创建自己用
1.2、解析
对于一个函数来说,函数体里面的就是自己本身的一个作用域,自己本身创建的变量,只能在自己本身的函数上面进行调用,别的函数不能进行调用。
1.3、相关代码
def f1 (a1): name = 'tang' print(name) def f2(): print(name) #f2的name没有进行定义变量,所以不能引用
2、全局变量
2.1、定义
在全局变量中所有作用域里面都可读、但不可修改
先执行自己
2.2、解析
被所有的函数都能使用的变量,没有写到函数里面的,直接写在文件当中
创建了全局变量,在f1函数中的也可以创建自己的局部变量,如果同一个变量,局部跟全局都有创建的话就会先去局部的
2.3、相关代码
name = 'tang' addr = 'xiamen' def f1 (): age = 19 addr = 'shanghai' #优先执行自己拥有的局部变量,但是不会改变全局变量的值,详见代码中的f2 print(age,name,addr) def f2(): age = 18 print(name,age,addr) f1() f2() #结果 #19 tang shanghai #tang 18 xiamen
3、修改全局变量--global
3.1、对全局变量进行重新赋值
对全局变量进行重新赋值,需要global
name = 'tang' addr = 'xiamen' def f1 (): age = 19 global addr #表示addr是全部变量,执行修改全局变量 addr = 'shanghai' #在函数里面修改全局变量 print(age,name,addr) def f2(): age = 18 print(name,age,addr) f1() f2() #结果 #19 tang shanghai #tang 18 tang 18 shanghai
3.2、对全局变量进行修改
对于列表、字典、元组里面嵌套的元素这三个特殊的类型,读取的时候可修改,但不可重新赋值
1 name = [11,22,33,44] 2 addr = 'xiamen' 3 def f1 (): 4 age = 19 5 print(name) 6 name.append(999) #对全局变量name进行修改成[11,22,33,44,999] 7 print(age,name,addr) 8 9 result = f1() 10 11 print(result) 12 13 def f2 (): 14 age = 19 15 print(name) 16 name.append(88) #对全局变量name进行修改成[11,22,33,44,999,88] 17 print(age,name,addr) 18 19 result2 = f2() 20 21 print(result2) 22 23 24 #执行结果 25 ''' 26 [11, 22, 33, 44] 27 19 [11, 22, 33, 44, 999] xiamen 28 None 29 [11, 22, 33, 44, 999] 30 19 [11, 22, 33, 44, 999, 88] xiamen 31 None 32 '''
4、书写规范
全局变量用全部大写的形式,这样在后面的定义全局变量的时候就比较容易知道是全局变量
NAME = 'tang' ADDR = 'xiamen' def f1 (): age = 19 global ADDR ADDR = 'shanghai' #在函数里面修改全局变量 print(age,NAME,ADDR) def f2(): age = 18 print(NAME,age,ADDR) f1() f2() #结果 #19 tang shanghai #tang 18 tang 18 shanghai
5、对于列表、字典这种嵌套的变量,可以直接在函数里面进行修改,但是不能进行重新赋值
十、函数式编程实现登录和注册
def login(username,password): """ 用于用户登录操作 :param username: 用户名 :param password: 密码 :return: 默认None """ f = open("db",'r') #以读的方式打开文件(db文件与本文件在同一个文件夹里面) for line in f: #一行一行读取文件里面的用户名、密码,一旦遇到符合条件的就会退出循环 line_list = line.strip().split("|") # db文件里面用户名、密码用|隔开,并且要加strip()移除换行符以及空白这些的影响 if line_list[0] == username and line_list[1] == password: #判断用户名、密码是否正确 return True #如果正确的话返回True return False def register(username,password): """ 用户用户注册操作 :param username:用户名 :param password:密码 :return:默认None """ f = open('db','a') #以a(追加)的方式打开,因为是要往文件里面写入用户名、密码,所以用a temp = "/n"+username+'|'+password #拼接一个字符串=用户名、密码 f.write(temp) #往拼接的字符串里面写入用户名、密码 f.close() #关闭文件 def main(): """ 主函数 :return: 默认None """ t = input('1:登录;2:注册') if t == '1': #因为前面输入的t是一个字符串,所以需要加引号当成是字符串或者是强制转换成int类型 user = input('请输入用户名:') #让用户输入用户名 pwd = input("请输入密码:") #让用户输入密码 r = login(user,pwd) if r: print('登录成功') elif t == '2': user = input('请输入用户名:') pwd = input("请输入密码:") register(user,pwd) main() #需要这步调用函数的操作,才会执行前面三个函数,不然不会执行 #strip():在login函数里面一定要有这一步,移除空白或者是换行符(因为添加了一个新的用户名、密码,如果不除掉换行符的话就会出现admin登录不了的现象) #函数与函数之间需要两个空格隔开,不然的话会出现波浪线--表示书写不规范 #上面的标注的话,需要三个双引号再敲回车即可
三元运算
一、三元运算(三目运算)
1、应用场景
对于简单的if else判断,都可以用三元运算来代替
#简单的if else判断 if 1==1: name = 'haha' else: name = "cuowu" #三元运算 name = "haha" if 1 ==1 else "cuowu"
lambda表达式
一、单个参数的lambda的表达式
对于简单的函数,可用lambda表达式来代替
自己隐含return功能
lambda表达式只能是一行,不能是多行
#简单的函数表达式 def f1(a1): return a1 +100 ret = f1(10) print(ret)
#lambda表达式代替函数 f2 = lambda a1:a1+100 ret = f1(10) print(ret)
二、支持多个参数
#lambda表达式支持多个参数 f2 = lambda a1,a2:a1+a2+100 ret = f2(10,11) print(ret) #运行结果:121