函数
数字类型
数字、字符串、字典、列表、元组、集合、队列、有序字典、默认字典等
初识函数
分类
—自定义函数
-内置函数
面向过程编程
-从上到下按照逻辑一点点写,遇到重复的功能,复制粘贴
-缺点:
-代码量多,可读性差
-代码重用性差
函数式编程
普通处理(while True功能)--报警代码重复
while True: if cpu利用率 > 90 %: # 发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 硬盘使用空间 > 90 %: # 发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 内存占用 > 80 %: # 发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接
函数式编程
1、声明函数:用名字带指,增强重用性
2、将重复的操作放在前面,并且跟定义变量一样,定义相同的操作为一个变量,再进行调用
3、变量名带指的东西:字符串、列表、元组
发送邮件 # 发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90 %: 发邮件 if 硬盘使用空间 > 90 %: 发邮件 if 内存占用 > 80 %: 发邮件
声明变量
python的解释器将代码从上到下执行,先声明变量,将变量存储到内存当中-在使用变量
name = 'tang' #声明变量 print(name) #使用变量
声明函数
python解释器将代码从上到下执行,一旦遇到def函数就表示要调用函数,函数里面的内容就是下图中的pass
def h1(): #def:关键字 函数名:h1 pass #函数的内容
函数的内存存储结构
-定义一个函数:
-def(关键字,解释器一旦遇到的话就表示要创建函数)
-函数名:h1
-括号:固定搭配
-函数内容:将一个功能都放在一块,以后调用的时候执行这个功能
-函数体:具体函数做什么操作
-返回值
举例:发送邮件的函数
代码:
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()
结构
函数内容里面的代码(函数体)是不执行的,只有在调用的时候才会执行。
函数内容只是存储到内存当中而已。
调用函数(执行函数):当调用函数的时候,函数内容的代码就会一句一句的执行
执行顺序
如下代码,执行顺序如下: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)
断点(额外补充)
作用:可以很方便的知道程序执行到哪一句
利用pycharm先在代码面前打断点
利用debug模式进行调试
执行第一个断点的时候会暂停执行,再次点击运行按钮的时候才会执行
debug模式:没有打断点的函数不会执行
备注点
python语言:程序是从上往下执行代码的
其他语言(C、java):将整个文件放在内存里面,执行的时候直接调用内存的文件即可
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)
返回值
定义
发送邮件的时候密码错误-邮件发送不成功
返回值:告知调用的人,邮件密码错误,发送是否成功
调用的时候接收返回值
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
停止
在函数中,一旦执行return的话,函数执行过程立即终止
执行顺序:1-6(h)-2-3-6(h1())-7
如果一个函数里面没有return的话,python里面会有一个默认的返回值:none
1 def h1(): 2 print(123) 3 return '111' #在函数中,一旦执行return的话,函数执行过程立即终止 4 print(456) 5 6 h = h1() 7 print(h) 8 9 #结果 10 #123 11 #111 12 13 14 15 #没有return 16 def h2(): 17 print(123) 18 19 h = h2() 20 print(h) 21 22 23 24 #结果 25 #123 26 #none
函数之基本参数
多个收件人
方法一、将全部的发邮件代码复制一遍,函数名修改成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') #调用函数 print(ret) #等于上面return的值赋值给sendmail() if ret == True: print("cc") else: print("ss")
形式参数:haha(传什么就变成什么)
实际参数:name1、name2、name3等传入的参数
括号()相当于一个容器,传的实际参数(name1、name2等),将传的值name1赋值给haha,在代码块里面都可以被使用。
执行步骤
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 #发送失败 #请输入邮箱地址:
多个形式参数
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 #发送成功 #请输入邮箱地址:
2、形式参数与实际参数的对应关系
默认情况下:一一对应
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
默认参数
如果传入的是两个参数的话,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
指定参数
def send (aaa,bbb): print(aaa,bbb) return True send('tang','mei') #默认参数 send(bbb='mei',aaa='tang') #指定参数 #结果 #tang mei #tang mei
动态参数
*号(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'>
**(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字典里面的元素拆开来
小总结
*:默认将传入的参数,全部放置在一个元组中,让函数去调用 f1(*{'n2':'tang2','n3':3})
**:默认将传入的参数,全部放置在一个字典中,让函数去调用 f1(**{'n2':'tang2','n3':3})
万能参数
不能将**放在后面,*放在前面,不然会报错
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功能
format函数:
python自带的函数
作用:格式化函数-用来格式化输出
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 #占位符要按照顺序,不能错开,不然会报错
传参放到一个列表里面,列表会被当做一个元素--如果是加*号的话就会将元素分离
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为传参数
字典方式
如果传的参数有一个为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、局部变量(自己创建自己用)
对于一个函数来说,函数体里面的就是自己本身的一个作用域,自己本身创建的变量,只能在自己本身的函数上面进行调用,别的函数不能进行调用。
def f1 (a1): name = 'tang' print(name) def f2(): print(name) #f2的name没有进行定义变量,所以不能引用
2、全局变量--在所有作用域里面都可读,但不可修改
被所有的函数都能使用的变量,没有写到函数里面的,直接写在文件当中
创建了全局变量,在f1函数中的也可以创建自己的局部变量,如果同一个变量,局部跟全局都有创建的话就会先去局部的
name = 'tang' addr = 'xiamen' def f1 (): age = 19 addr = 'shanghai' print(age,name,addr) def f2(): age = 18 print(name,age,addr) f1() f2() #结果 #19 tang shanghai #tang 18 xiamen
3、修改全局变量--global
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
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登录不了的现象) #函数与函数之间需要两个空格隔开,不然的话会出现波浪线--表示书写不规范 #上面的标注的话,需要三个双引号再敲回车即可