命名关键字参数,函数对象,嵌套,名称空间与作用域,闭包

Posted 596014054-yangdongsheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了命名关键字参数,函数对象,嵌套,名称空间与作用域,闭包相关的知识,希望对你有一定的参考价值。

一、命名关键字参数

对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数  。至于到底传入了哪些,就需要在函数内部通过kw检查。

仍以person()函数为例,我们希望检查是否有cityjob参数:

技术分享图片
def person(name, age, **kw):
    if city in kw:
        # 有city参数
        pass
    if job in kw:
        # 有job参数
        pass
    print(name:, name, age:, age, other:, kw)
View Code

但是调用者仍可以传入不受限制的关键字参数:

person(Jack, 24, city=Beijing, addr=Chaoyang, zipcode=123456)

如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收cityjob作为关键字参数。这种方式定义的函数如下:

技术分享图片
def person(name, age, *, city, job):
    print(name, age, city, job)
View Code

和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数。

调用方式如下:

技术分享图片
person(Jack, 24, city=Beijing, job=Engineer)
Jack 24 Beijing Engineer
View Code

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:

技术分享图片
def person(name, age, *args, city, job):
    print(name, age, args, city, job)
View Code

命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:

person(Jack, 24, Beijing, Engineer)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given

由于调用时缺少参数名cityjob,Python解释器把这4个参数均视为位置参数,但person()函数仅接受2个位置参数。

在*后面的参数都是命名关键字参数,传值的时候必须按照关键字参数进行传值,*args后面的参数也是命名关键字参数,命名关键字参数可以有缺省值(city是默认参数可以不传值),从而简化调用:

def person(name, age, *, city=Beijing, job):
    print(name, age, city, job)

由于命名关键字参数city具有默认值,调用时,可不传入city参数 

使用命名关键字参数时,要特别注意,如果没有可变参数,就必须加一个*作为特殊分隔符。如果缺少*,Python解释器将无法识别位置参数和命名关键字参数:

技术分享图片
def person(name, age, city, job):
    # 缺少 *,city和job被视为位置参数
    pass
View Code

 二、函数对象

函数是第一类对象: 指的是函数的内存地址可以像一个变量值一样去使用

def foo():        foo=函数的内地址
    print(‘from foo‘)

1. 变量值可以被引用
技术分享图片
x=1    #foo=函数的内地址
y=x
f=foo
print(f)
f()
View Code

2. 变量值可以当作参数传给另外一个函数

技术分享图片
def bar(x):
   print(x)
   x()
x=11111       #foo=函数的内存地址
bar(x)
bar(foo)
View Code

3. 变量值可以当作函数的返回值

技术分享图片
def func(x):
    return x

f=func(foo)
print(f)
View Code
4. 变量值可以当作容器类型的元素
技术分享图片
l=[foo,]
print(l)
l[0]()

dic={1:foo}
print(dic)
dic[1]()

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

    if choice not in func_dic:
        print(输错的指令不存在)
        continue

    func_dic[choice]()
View Code

 三、函数的嵌套

函数的嵌套调用:在一个函数内部又调用其他函数

技术分享图片
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))
View Code

函数的嵌套定义: 在函数内又定义了其他函数

技术分享图片
def func():
   def foo():
      print(from foo)
   print(foo)
   foo()
   x=1
   print(x)

func()
View Code

四、 名称空间与作用域

4.1 名称空间相关
名称空间Namespaces:指的就是存放名字与值内存地址绑定关系的地方(内存空间)

4.2 名称空间分为三大类
内置名称空间: 存放的是python解释器自带的名字
   产生:python解释器的启动则产生
   销毁:python解释器关闭则销毁

全局名称空间: 在顶级定义的名字

技术分享图片
x=1
if True:
  y=2
while True:
  z=3
def func():
  pass
View Code

    产生:执行python程序时产生
    销毁:python程序执行完毕后则销毁

局部名称空间: 在函数内定义的名字

技术分享图片
def foo():
  m=100

foo()
View Code

    产生: 在函数调用时临时产生
    销毁: 在函数调用完毕后则销毁

三种名称空间的产生的先后顺序: 内置->全局->局部
查找名字的顺序:从当前位置往外一层一层查找
如果当前在局部名称空间: 局部->全局->内置
如果当前在全局名称空间: 全局->内置

4.3 作用域:指的是作用范围
全局作用域:包含内置与全局名称空间的名字
   特点:全局存活,全局有效
局部作用域:包含局部名称空间的名字
   特点:临时存活,局部有效

全局作用域:包含的是内置名称空间与全局名称空间的名字,
特点
   在任何位置都能够访问的到
   该范围内的名字会伴随程序整个生命周期

局部作用域:包含的是局部名称空间的名字
特点:
   只能在函数内使用
   调用函数时生效,调用结束失效

!!!作用域关系是在函数定义阶段就已经固定死了,与调用位置无关
示范一:

技术分享图片
def f1():
  print(xxx)

xxx=111

def f2():
  xxx=222
  f1()

f2()
View Code

示范二:

技术分享图片
xxx=111
yyy=333
def f1():
  xxx=222
  print(xxx)
  #xxx=222
  yyy=222
  print(yyy)

f1()
View Code

五、闭包函数

闭:封闭,指的是该函数是定义一个函数内部的函数

包:该内部函数包含对外层函数名字的引用

技术分享图片
def outter():
    x=1
    def inner():
        print(from inner,x)
    return inner


f=outter()

def foo():
    # print(f)
    x=111111111111111111111111111111111111
    f()
foo()
View Code

为函数体传值的两种方式
方式一:直接以参数的形式传入

技术分享图片
def foo(name):
  print(hello %s %name)

foo(egon)
foo(egon)
foo(egon)
View Code

方式二:闭包函数

技术分享图片
def outter(name):
    # name=‘egon‘
    def foo():
        print(hello %s %name)
    return foo

f=outter(egon)
# print(f)
f()
f()
f()

f1=outter(alex)
f1()
f1()
f1()
View Code

pip3 install requests
import requests

问题

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)
get(https://www.baidu.com)
get(https://www.baidu.com)
解决方案一
技术分享图片
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()
baidu()
baidu()
baidu()
baidu()
baidu()
baidu()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
cnblogs()
解决方案二

 














































以上是关于命名关键字参数,函数对象,嵌套,名称空间与作用域,闭包的主要内容,如果未能解决你的问题,请参考以下文章

函数对象函数嵌套名称空间与作用域装饰器

函数基础2

函数参数补充名称空间与作用域global与nonlocal

python--函数的返回值函数参数的使用名称空间与作用域函数嵌套函数对象

python之旅:函数对象函数嵌套名称空间与作用域装饰器

可变长参数函数对象嵌套名称空间和作用域