4、函数
1.什么是函数?
具备某一功能的函数,事先准备好一个工具
2,为何要使用函数?
1>.不适应函数组织结构不清晰,可读性差
2>.代码冗余,不好维护
3>.如何使用函数
原则:先定义后调用
4.1定义函数
'''
def 函数名(参数1,参数2):
"""文档注释"""
函数体
return 值
'''
4.1.1无参函数
# 方式一:无参函数
def func():
print('hhhh')
func()
# 定义函数发生的事情
# 1.申请内存空间保存函数体代码
# 2.将内存地址绑定给函数名
# 定义的时候不会执行函数体代码,但是会检测函数体语法是否正确
# 调用函数发生的事情
# 1.通过函数名找到内存地址
# 2.加括号就是在触发函数体代码的执行
# print(func())
x=11
def bar():
print('from bar')
def foo():
print(bar) # bar = 函数的内存地址
print('from foo')
bar()
foo()
# 应用场景:无参函数 不需要传参数的
def interactive():
name=input('username:')
age=input('age:')
mas='姓名:{} 年龄:{}'.format(name,age)
print(mas)
interactive()
4.1.2有参函数 空函数
# 方式二:有参函数
def func(x,y):
print(x+y)
func(1,2)
# 形式三:空函数 函数体代码为pass
def func():
pass
func()
# 应用场景:有参函数 需要传参数的,参数就好比原材料
def add(x,y):
res=x+y
print(res)
add(20,30)
# 应用场景:空函数
# 在构思函数的时候使用,最好写上注释
def upload_file():
"""upload file function"""
pass
4.2调用函数的三种形式
# 调用函数的三种方式
# 方式一:语句的形式 只调用函数,不做任何操作
# interactive()
# add(20,30)
# 方式二:表达式形式
def add(x,y):
res=x+y
return res
# 赋值表达式
res=add(10,20)
print(res)
#数学表达式
res=add(10,20)*10
print(res)
# 方式三:函数调用可以当做参数
def add(x,y):
res=x+y
return res
res=add(add(1,2),3)
print(res)
4.3函数返回值
# 函数的返回值
# return是函数结束的标志,即函数体代码一旦运行到return就会立刻终止函数的运行 并且会将return后面的值当做本次运行的结果返回
# 返回None 函数体内没有return return return None
# 返回一个值 return 值
# def func():
# return 10
# res=func()
# print(res)
# 返回多个值 用逗号分隔开 会被return返回成元组
def func():
return 10,'aa',20
res=func()
print(res)
4.4参数
形参与实参的介绍
形参:在定义函数阶段定义的参数称为形式参数
实参:在调用函数阶段传入的参数称为实际参数
两者的关系是:
1.在调用阶段实参会绑定给形参 这种绑定关系只能在函数体内使用
2.实参与形参的绑定关系只能在函数调用时生效,函数调用结束后解除绑定关系
# 实参相当于值,值可以是以下几种形式
# 形式一
# func(1,2)
# 形式二:
# a=1
# b=2
# func(a,b)
# 形式三
# func(int('1'),2)
# 位置参数 按照从左到右的顺序依次定义的参数
# 位置形参 在定义定义阶段,按照从左到右的顺序直接定义的变量名
# 特点:必须要传值,多一个不行,少一个不行
# def func(x,y):
# print(x,y)
# 位置实参 在函数调用阶段 按照从左到右的顺序依次传递值
# 特点:按照顺序与形参一一对应
# 关键字实参 在函数调用阶段,按照key=value的形式传入的值
# 特点:可以完全不参照顺序
# def func(x,y):
# print(x,y)
# func(y=1,x=2)
# 混合使用
# 位置实参必须放在关键字实参前
# func(1,x=2)
# 不能为同一个形参重复传值
# func(1,x=2,y=3)
# 默认参数 默认形参
# 默认形参 在定义函数阶段,就已经被赋值的形参
# 特点:在定义阶段就已经被赋值,赋值的是内存地址 在调用阶段就可以不用赋值
# 位置形参必须在默认形参的左边
# def register(name,age,gender='男'):
# print(name,age,gender)
#
# register('1',12,'男')
# register('2',12,'男')
# register('3',13,'男')
# m=2
# def func(x,y=m): # y=>2的内存地址
# print(x,y)
# m=3
# func(1)
# m=[12]
# def f2(x,y=m):# m作为列表,内存地址
# print(x,y)
# m.append(23)
# f2(2)
# 虽然默认值可以指定为任意数据类型,但是不推荐使用可变类型
# 函数最理想的状态,只跟函数本身有关系,不受其他代码的影响
# def f1(x,y,z,l=None):
# if l is None:
# l=[]
# l.append(x)
# l.append(y)
# l.append(z)
# print(l)
# new_l=[11,22]
# f1(1,2,3,new_l)
# 可变长度的参数 指的是在调用函数时,传入的实参的个数不固定的
# 而实参是用来为形参赋值的,所以针对着溢出的实参必须有相应的实参来接收
# * 形参名:用来接收溢出的位置实参溢出的位置实参会被*保存成元组的形式 约定俗成的是args
# def func(x,y,*args):
# print(x,y,args)
#
# func(1,2,3,4,5)
# * 可以用在实参中 会把*后面的值打散成位置实参 *后面的值的个数要和形参的个数一样,多一个或者少一个都会报错
# def func(x,y):
# print(x,y)
#
# func(*[1,2])
# 形参和实参中都带*
# def func(x,y,*args):
# print(x,y,args)
#
# func(1,2,*[1,2])
# 可变长度的关键字实参
# **形参名:用来接收溢出的关键字实参,**会将溢出的形参保存为字典格式 约定俗成的就是kwargs
# def func(x,y,**kwargs):
# print(x,y,kwargs)
#
# func(x=1,y=2,c=3,b=4,d=5)
# ** 可以用在实参中,**后的值只能是字典
# def func(x,y,z):
# print(x,y,z)
#
# func(**{'x':2,'y':1,'z':4,})
# # 实参和形参都可以使用**
# def func(x,y,**kwargs):
# print(x,y,kwargs)
#
# func(**{'y':222,'x':111,'a':12,'b':34})
# 混用* 和 **:先使用* 在使用**
# def func(x,*args,**kwargs):
# print(x)
# print(args)
# print(kwargs)
#
# func(1,2,3,y=2)
# 命名关键字参数
# 在定义函数时,* 后定义的参数 称之为关键字参数
# def func(x,y,*,a,b): # 其中,a,b称为命名关键字参数
# print(x,y)
# print(a,b)
#
# func(1,2,a=3,b=4)
def func(x,y,*,a=3,b): # 其中,a,b称为命名关键字参数
print(x,y)
print(a,b)
func(1,2,b=4)
# 组合使用
# 位置形参 默认形参 *args 关键字形参 **kwargs
# def func(x,a=1,*args,b,**kwargs):
# print(x)
# print(a)
# print(*args)
# print(b)
# print(**kwargs)
4.5名称空间
名称空间namespacs:存放名字的地方,是对栈区的划分,有了名称空间之后,就可以在栈区中存放相同的名字,详细的,名称空间
# 分为三种
# 1.1 内置名称空间
# 存放的名字:存放的python解释器内置的名字
'''
>>> print
<built-in function print>
>>> input
<built-in function input>
'''
# 存活周期:python解释器启动则产生,python解释器关闭则销毁
# 1.2 全局名称空间
# 存放的名字:只要不是函数内定义、也不是内置的,剩下的都是全局名称空间的名字
# 存活周期:python文件执行则产生,python文件运行完毕后销毁
# import os
#
# x=10
# if 13 > 3:
# y=20
# if 3 == 3:
# z=30
#
# # func=函数的内存地址
# def func():
# a=111
# b=222
# class Foo:
# pass
# 1.3 局部名称空间
# 存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字
# 存活周期:在调用函数时存活,函数调用完毕后则销毁
# def func(a,b):
# pass
#
# func(10,1)
# func(11,12)
# func(13,14)
# func(15,16)
# 1.4 名称空间的加载顺序
# 内置名称空间>全局名称空间>局部名称空间
# 1.5 销毁顺序
# 局部名称空间>全局名空间>内置名称空间
# 1.6 名字的查找优先级:当前所在的位置向上一层一层查找
# 内置名称空间
# 全局名称空间
# 局部名称空间
# 如果当前在局部名称空间:
# 局部名称空间—>全局名称空间->内置名称空间
# # input=333
#
# def func():
# # input=444
# print(input)
#
# func()
# 如果当前在全局名称空间
# 全局名称空间->内置名称空间
# input=333
# def func():
# input=444
# func()
# print(input)
# 示范1:
# def func():
# print(x)
# x=111
#
# func()
# 示范2:名称空间的"嵌套"关系是以函数定义阶段为准,与调用位置无关
# x=1
# def func():
# print(x)
#
#
# def foo():
# x=222
# func()
#
# foo()
# 示范3:函数嵌套定义
# input=111
# def f1():
# def f2():
# # input=333
# print(input)
# input=222
#
# f2()
#
#
# f1()
# 示范4:
# x=111
# def func():
# print(x) #
# x=222
#
# func()
# 二:作用域-》作用范围
# 全局作用域:内置名称空间、全局名称空间
# 1、全局存活
# 2、全局有效:被所有函数共享
# x=111
#
# def foo():
# print(x,id(x))
#
# def bar():
# print(x,id(x))
#
# foo()
# bar()
# print(x,id(x))
# 局部作用域: 局部名称空间的名字
# 1、临时存活
# 2、局部有效:函数内有效
# def foo(x):
# def f1():
# def f2():
# print(x)
# LEGB
# # builtin
# # global
# def f1():
# # enclosing
# def f2():
# # enclosing
# def f3():
# # local
# pass
# 示范1:
# x=111
#
# def func():
# x=222
#
# func()
# print(x)
# 示范2:如果再局部想要修改全局的名字对应的值(不可变类型),需要用global
# x=111
#
# def func():
# global x # 声明x这个名字是全局的名字,不要再造新的名字了
# x=222
#
# func()
# print(x)
# 示范3:
# l=[111,222]
# def func():
# l.append(333)
#
# func()
# print(l)
# nonlocal(了解): 修改函数外层函数包含的名字对应的值(不可变类型)
# x=0
# def f1():
# x=11
# def f2():
# nonlocal x
# x=22
# f2()
# print('f1内的x:',x)
#
# f1()
# 可变类型直接改就可以了
def f1():
x=[]
def f2():
x.append(1111)
f2()
print('f1内的x:',x)
f1()
4.6函数对象
精髓:可以把函数当成变量去用
#func=内存地址
# 函数可以被当做数据去处理
# def func():
# print('from func')
# func()
# 1,可以赋值
# def func():
# print('from func')
# f=func # 指向同一个内存地址
# print(f,func)
# 2.可以把函数当成参数传给另外一个函数
# def foo(x):
# print(x)
# x() # <function func at 0x000001817D74A710>
# foo(func) # foo(func的内存地址) 地址给了x
# 3.可以把函数当做另外一个函数的返回值
def func():
print('from func')
def foo(x):
return x
res=foo(func)
print(res)
res()
# 4.函数可以作为容器类型的元素
# def func():
# print('from func')
# l=[func]
# print(l)
# l[0]()
# def func():
# print('from func')
# dic={'k1':func}
# dic['k1']()
函数对象示范
# def login():
# print('登录功能')
#
#
# def transfer():
# print('转账功能')
#
#
# def check_banlance():
# print('查询余额')
#
# def withdraw():
# print('提现')
#
#
# def register():
# print('注册')
#
# func_dic={
# '1':login,
# '2':transfer,
# '3':check_banlance,
# '4':withdraw,
# '5':register
# }
#
# # func_dic['1']()
#
#
# while True:
# print("""
# 0 退出
# 1 登录
# 2 转账
# 3 查询余额
# 4 提现
# 5 注册
# """)
# choice = input('请输入命令编号:').strip()
# if not choice.isdigit():
# print('必须输入编号,傻叉')
# continue
#
# if choice == '0':
# break
#
#
# if choice in func_dic:
# func_dic[choice]()
# else:
# print('输入的指令不存在')
#
# # if choice == '1':
# # login()
# # elif choice == '2':
# # transfer()
# # elif choice == '3':
# # check_banlance()
# # elif choice == '4':
# # withdraw()
# # else:
# # print('输入的指令不存在')
# 修正
def login():
print('登录功能')
def transfer():
print('转账功能')
def check_banlance():
print('查询余额')
def withdraw():
print('提现')
def register():
print('注册')
func_dic = {
'0': ['退出', None],
'1': ['登录', login],
'2': ['转账', transfer],
'3': ['查询余额', check_banlance],
'4': ['提现', withdraw],
'5': ['注册', register]
}
# func_dic['1']()
while True:
for k in func_dic:
print(k, func_dic[k][0])
choice = input('请输入命令编号:').strip()
if not choice.isdigit():
print('必须输入编号,傻叉')
continue
if choice == '0':
break
# choice='1'
if choice in func_dic:
func_dic[choice][1]()
else:
print('输入的指令不存在')
4.7函数嵌套
函数的嵌套调用:在调用一个函数的过程中又调用其他函数
# def max2(x,y):
# if x > y:
# return x
# else:
# return y
#
#
# def max4(a,b,c,d):
# # 第一步:比较a,b得到res1
# res1=max2(a,b)
# # 第二步:比较res1,c得到res2
# res2=max2(res1,c)
# # 第三步:比较res2,d得到res3
# res3=max2(res2,d)
# return res3
#
# res=max4(1,2,3,4)
# print(res)
# 2、函数的嵌套定义:在函数内定义其他函数
# def f1():
# def f2():
# pass
# 圆形
# 求圆形的求周长:2*pi*radius
def circle(radius,action=0):
from math import pi
def perimiter(radius):
return 2*pi*radius
# 求圆形的求面积:pi*(radius**2)
def area(radius):
return pi*(radius**2)
if action == 0:
return 2*pi*radius
elif action == 1:
return area(radius)
circle(33,action=0)
4.8闭包函数
闭包函数=名称空间与作用域+函数嵌套+函数对象
核心点:名字的查找关系是以函数定义阶段为准
什么是闭包函数?
"闭"函数指的该函数是内嵌函数
"包"函数指的该函数包含对外层函数作用域名字的引用(不是对全局作用域)
闭包函数:名称空间与作用域的应用+函数嵌套
# def f1():
# x = 33333333333333333333
# def f2():
# print(x)
# f2()
#
#
# x=11111
# def bar():
# x=444444
# f1()
#
# def foo():
# x=2222
# bar()
#
# foo()
# 闭包函数:函数对象
# def f1():
# x = 33333333333333333333
# def f2():
# print('函数f2:',x)
# return f2
#
# f=f1()
# # print(f)
#
# # x=4444
# # f()
# def foo():
# x=5555
# f()
#
# foo()
# 三:为何要有闭包函数=》闭包函数的应用
# 两种为函数体传参的方式
# 方式一:直接把函数体需要的参数定义成形参
# def f2(x):
# print(x)
#
# f2(1)
# f2(2)
# f2(3)
# 方式二:
# def f1(x): # x=3
# x=3
# def f2():
# print(x)
# return f2
#
# x=f1(3)
# print(x)
#
# x()
import requests
# 传参的方案一:
# def get(url):
# response=requests.get(url)
# print(len(response.text))
#
# get('https://www.baidu.com')
# get('https://www.cnblogs.com/linhaifeng')
# get('https://zhuanlan.zhihu.com/p/109056932')
# 传参的方案二:
def outter(url):
# url='https://www.baidu.com'
def get():
response=requests.get(url)
print(len(response.text))
return get
baidu=outter('https://www.baidu.com')
baidu()
cnblogs=outter('https://www.cnblogs.com/linhaifeng')
cnblogs()
zhihu=outter('https://zhuanlan.zhihu.com/p/109056932')
zhihu()
标签:f2,return,函数,func,print,def
From: https://www.cnblogs.com/xionghuan01/p/16638835.html