1.昨天函数的参数内容的补充
命名关键字参数: 在定义函数时,*与**之间参数称之为命名关键字参数
特点:
在调用函数时,命名关键字参数必须按照key=value的形式传值
def func(x,*,y=1,z): 在这里*后边的y和z都是命名关键字参数,y像默认参数一样被事先赋值好了,再实
参进行传值的时候可以不对y进行传值
print(x)
print(y)
print(z)
func(1,z=2) 传值的时候必须要使用key=value的形式才可以传值成功.
def func(a,b=2,*args,c,**kwargs): 设置形参时各种形参的位置顺序
print(a)
print(b)
print(args)
print(c)
print(kwargs)
------------------------------------------------------------------------------------分割线----------------------------------------------------------------------------
一、函数对象
函数是第一类对象: 指的是函数的内存地址可以像一个变量值一样去使用
def foo(): #foo 不加括号代表函数的内存地址
print('from foo')
1. 变量值可以被引用
x=1 #foo=函数的内存地址
y=x
f=foo
print(f) 输出:<function foo at 0x0000024CF6E63E18>
f() 输出:from foo
2. 变量值可以当作参数传给另外一个函数
def bar(x): 这时的x=foo
print(x) 将函数foo的内存地址打印出来
x() 相当于调用函数foo(),会实现foo的功能
bar(foo) 函数bar中的参数为函数foo(foo的内存地址)
3. 变量值可以当作函数的返回值
def func(x):
return x 将foo当做返回值返回
f=func(foo) 将foo当做参数传给函数func,接受参数为foo时func的返回值
print(f) 其实这里打印的还是foo的内存地址
4. 变量值可以当作容器类型中(容器类型指的是:元组、列表、字典)的元素
l=[foo,] 将foo当做列表中的元素
print(l) 输出:[<function foo at 0x0000016828A43E18>]
l[0]() 使用列表的特点调用函数foo
dic={'1':foo} 将foo当做字典中的元素
print(dic)
dic['1']() 使用字典特点调用函数foo
-----------------------------------------------------------------------使用函数对象的第四个特点对简易购物车进行优化--------------------------------
def register(): 前面定义函数实现相应的功能
print('注册....')
def login():
print('登录....')
def pay():
print('支付....')
def transfer():
print('转账....')
func_dic={ 利用函数对象的第四个特点,将函数(内存地址)存放在字典中
'1':register,
'2':login,
'3':pay,
'4':transfer
}
#func_dic['1']() 可以使用这样的形式直接调用相应功能的函数
'''
整体代码就不用写特别长了,并且可拓展性相对于之前来说好了很多,想要添加什么功能,直接定义函数实现功能的添加,然后在字典中添加新功能对应的键值对,再在打印阶段打印出新功能的提示信息就可以了,主代码并不需要改动即可实现新功能的添加
'''
while True:
print("""
0 退出
1 注册
2 登录
3 支付
4 转账
""")
choice=input('请输入你的操作: ').strip()
if choice == '0':break 这里输入0对应的操作代码不能喝下面的判断代码互换位置,换了位
置之后就不能实现退出的功能,会被判定为为错误的指令输入,因为字
典中的key没有0
if choice not in func_dic:
print('输错的指令不存在') 判断输入的指令编号是否存在与字典中
continue
func_dic[choice]() 执行相应key对应的函数
二、函数嵌套
函数的嵌套调用:在一个函数内部又调用其他函数
def max2(x,y):
if x > y:
return x
else:
return y
def max4(a,b,c,d):
res1=max2(a,b) 在一个函数中又调用其他的函数
res2=max2(res1,c)
res3=max2(res2,d)
return res3
print(max4(1,2,3,4))
函数的嵌套定义: 在函数内又定义了其他函数
def func():
def foo(): 在func中嵌套定义函数foo
print('from foo')
# print(foo) 如果在这里打印foo打印出来的是foo的内存地址
foo() 在func中也可以直接调用定义好的foo
x=1
print(x) 这里x的值为1
func()
-------------------------------------------函数嵌套的使用---------------------------------
使用函数嵌套可以将同系列的函数功能统一到一个函数里边,简化了函数的调用
下边是一个函数嵌套的例子
from math import pi
def circle(radius,action): 可以直接通过参数来选择来进行的操作,是要结算周长还是计算面积
def cal_perimeter():
return 2 * pi * radius
def cal_area():
return pi * (radius ** 2)
if action == 1:
res=cal_perimeter()
elif action == 2:
res=cal_area()
return res
res=circle(10,1)
print(res)
三、函数的名称空间和作用域
一 、名称空间相关
1. 名称空间Namespaces:指的就是存放名字与值内存地址绑定关系的地方(内存空间)
x=1,需要在内存中申请一个空间来存放1这个值,同时还要寻找一个内存空间来存储x和1的内存地址绑定关系的空间,存放名字与值对应绑定关系的地方就成为名称空间,
2. 名称空间分为三大类
内置名称空间: 存放的是python解释器自带的名字(例如len()、print()、等等)
产生:python解释器的启动则产生
销毁:python解释器关闭则销毁
全局名称空间: 在顶级代码中定义的名字
产生:执行python程序时产生
销毁:python程序执行完毕后则销毁
x=1
if True:
y=2
while True:
while True:
while True:
z=3 z=3在这里也算做顶级代码中定义的名字,因为while循环是一直往下走的一直走到了z=3,相当于写了一行代码,只不 过z=3写在最后边而已,也是存在于全局名称空间中的.
局部名称空间: 在函数内定义的名字
产生: 在函数调用时临时产生
销毁: 在函数调用完毕后则销毁
def foo():
m=100 比如这里的m就属于局部名称空间中的,局部名称都是函数调用时临时产生临时销毁的
foo()
三种名称空间的产生的先后顺序: 内置->全局->局部
查找名字的顺序:从当前位置往外一层一层查找 查找名字指的是在执行当前代码时,所需要用到的变量名的名字,并这行代 码所在位置就是当前位置
如果当前在局部名称空间: 局部->全局->内置
如果当前在全局名称空间: 全局->内置
# len=111
# def foo():
# # len=222
# print(len) 在这里打印len的时候,首先从局部名称空间找,找到len=222,
# len=111 如果局部空间len=222不存在,就从全部名称空间找,可以找到len=111,
如果全部名称空间的len=111不存在,就从内置名称空间中找,这时候打印出来
的len就是python解释器中求长度的函数len()的内存地址
# foo()
# x=0
def f1():
# x=1
def f2():
# x=2
def f3():
# x=3
print(x)
f3()
f2()
f1() 在f1()的最终结果中x=0,x=1,x=2,x=3都存在话,f1()的最终结果为x=3,如果从x=3.x=2,x=1,x=0一
次被注释掉的时候,f1()的最终结果依次为3,2,1,0 这就是函数嵌套时寻找变量名的顺序
def foo1():
def foo2():
def foo3():
print(x)
'''
二 、作用域:指的是作用范围
全局作用域:包含内置名称空间与全局名称空间的名字
特点:全局存活(该范围内的名字会伴随程序整个的生命周期,即从读取出来到运行完毕关闭的时候),
全局有效(在任何位置都能访问的到)
局部作用域:包含的是局部名称空间的名字
特点:临时存活(只有在调用函数时生效,调用结束时失效)
局部有效(只能在函数内使用)
作用域关系是在函数定义阶段就已经固定死了,与调用位置无关
示范一:
def f1():
print(xxx)
xxx=111
def f2():
xxx=222
f1() 在这里调用f1()时打印出来的值并不是222因为f1中xxx的值在定义阶段已经被定义了xxx=111
无论在哪个地方调用f1,打印出来的值都是111
示范二:
xxx=111
def f1():
print(xxx) 这里程序会进行报错,原因是在定义阶段已经就近找到了xxx的值为222但是在函数
调用阶段又出现了xxx=111的情况,和定义的时候出现了冲突,去掉函数头顶的
xxx=111即可正常使用函数,这时xxx的值为222
xxx=222
yyy=222
print(yyy) 这里的yyy是可以正常输出的,在定义阶段yyy=222,调用函数的时候没有与定义阶
段冲突,但是如果在函数头顶加上yyy=333时,调用时就会出现和xxx一样的错误
f1()
(全局/局部)名称空间:是存放值与变量名绑定关系的内存空间,是存(全局/局部)变量的地方
(全局/局部)作用域:指的是(全局/局部)变量起作用的范围
(全局/局部)变量:存放在(全局/局部)名称空间中,在代码中体现为全局变量是在顶级代码的位置的,局部变量是在函数体内部的
四、闭包函数
闭包函数:
闭:封闭,指的是该函数是定义一个函数内部的函数
包:该内部函数包含对外层函数名字(这里的外层函数名字指的是外层函数包含的局部变量)的引用
def outter(): inner在这里就是一个典型的闭包函数,它定义在outter()内部,在inner
中使用的x属于outter的局部变量,也就是相对于inner来说的外部函数名
字的引用.
x=1
def inner():
print('from inner',x)
return inner
f=outter()
def foo():
# print(f)
x=111111111111111111111111111111111111
f() 在这调用f()时,x的值不会受到x=11111111111111111111111的影响,因为在f()定义阶段
x=1
foo()
为函数体传值的两种方式:
def foo():
print('hello %s' %name)
方式一:直接以参数的形式传入
def foo(name):
print('hello %s' %name)
foo('egon')
foo('egon')
foo('egon') 这种在调用的时候每次都要输入要传给参数的内容,调用的时候如果遇到要经常传较长内容内参数的时候就会比较麻烦
方式二:闭包函数(使用闭包函数传值给函数体)
def outter(name):
# name='egon'(省略了这一步)
def foo():
print('hello %s' %name)
return foo
f=outter('egon') 之后就可以直接调用f()就可以打印出来hello egon
# print(f)
f()
f()
f()
f1=outter('alex')
f1()
f1()
f1()
pip3 install requests 安装python中爬虫必要的组件,直接在cmd中输入改命令就可以
闭包函数的简单应用
import requests
问题 要给url传值(也就是需要爬的网站名字)
def get():
response=requests.get(url)
if response.status_code == 200:
print(response.text)
解决方案一:(设置参数,给参数赋值)
def get(url):
response=requests.get(url)
if response.status_code == 200:
print(response.text)
get('https://www.baidu.com') 缺点:每次爬取都需要给参数url传内容,调用比较麻烦
get('https://www.baidu.com')
get('https://www.baidu.com')
解决方案二:(使用闭包函数给url传值)
def outter(url):
# url='https://www.baidu.com'
def get():
response=requests.get(url)
if response.status_code == 200:
print(response.text)
return get
baidu=outter('https://www.baidu.com') 一次传值后赋值给变量名,以后可以重复使用
cnblogs=outter('https://www.cnblogs.com')
baidu()
baidu()
baidu()
baidu()
baidu()
baidu()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()