函数的进阶

一.函数的动态参数

1.*args 位置参数动态传参

在参数位置编写*表示接受任意内容

def a(*food):
    print(food)
a('福建人','老鼠','')
a('虎鞭','牛鞭')
a('蝗虫')
a()

结果:
('福建人','老鼠','')
('虎鞭','牛鞭')
('蝗虫')
()
def chi(*food):
      print("我要吃", food)

chi("大米饭", "小米饭") 

结果: 
我要吃 (
'大米饭', '小米饭') # 多个参数传递进去. 收到的内容是元组tuple

注意:动态接受参数的时候要注意,动态参数必须在位置参数后面

def chi(*food, a, b):
     print("我要吃", food, a, b)

# chi("大米饭", "小米饭", "黄瓜", "茄子")   # 错 
chi("大米饭", "小米饭", a="黄瓜", b="茄子")   # 必须⽤用关键字参数来指定
def chi(a, b, *food):
      print("我要吃", a, b, food)
chi("大米饭", "小米饭", "馒头", "面条")   # 前两个参数用位置参数来接收, 后面的参数用 动态参数接收

默认值参数

def chi(a, b, c='馒头', *food):
      print(a, b, c, food)
chi("香蕉", "菠萝")  # 香蕉 菠萝 馒头 () ,默认值生效
chi("香蕉", "菠萝", "葫芦娃")  # 香蕉 菠萝 葫芦娃 () ,默认值不生效
chi("香蕉", "菠萝", "葫芦娃", "口罩")    # 香蕉 菠萝 葫芦娃 ('口罩',) ,默认值不生效

默认值在动态参数之前只有一种情况才可生效,所以:

def chi(a, b, *food, c="娃哈哈"):
print(a, b, food, c)
chi("香蕉", "菠萝")  # 香蕉 菠萝 () 娃哈哈    ,默认值生效 
chi("香蕉", "菠萝", "葫芦娃")  # 香蕉 菠萝 ('葫芦娃',) 娃哈哈    ,默认值生效
chi("香蕉", "菠萝", "葫芦娃", "口罩")    # 香蕉 菠萝 ('葫芦娃', '口罩') 娃哈哈    ,默认值⽣生效

这时所有的默认值都生效了,如果不使用关键字传参,修改默认值,你的默认值是永远都会有效的

2.**kwargs 关键字参数动态传参

def chi(**food):
    print(food)
chi(广东人 = '福建人',山东人 = '大葱',东北人 = '大蒜',四川人 = '辣椒')

结果:
{'广东人': '福建人', '山东人': '大葱', '东北人': '大蒜', '四川人': '辣椒'}
def func(**kwargs):
    print(kwargs)

func(a=1, b=2, c=3)
func(a=1, b=2)

结果:
{'a': 1, 'b': 2, 'c': 3}
{'a': 1, 'b': 2}

这时候接受的是一个字典(dict)

在函数调用的时候,如果先给出关键字参数,则整个参数列表会报错

def func(a, b, c, d):
     print(a, b, c, d)

# 关键字参数必须在位置参数后⾯面, 否则参数会混乱
func(1, 2, c=3, 4)

所以关键字参数必须在位置参数后面,由于实参是这个顺序,所以形参接受的时候也是这个顺序,

也就是说位置参数必须在关键字参数前面,动态接收关键字参数也要在后面

顺序:位置参数,*args,默认值,**kwargs

def func(*args, **kwargs)   #无敌传参

  pass

接受所有的参数:

def func(*args, **kwargs):
    print(args, kwargs)

func("麻花藤","马晕",wtf="胡辣汤")

形参的位置: *,**:聚合

实参的位置: *,**:打散

def fun(*args):
    print(args)

lst = [1, 4, 7]
fun(lst[0], lst[1],lst[2])

fun(*lst)   # 可以使用*把一个列表按顺序打散
s = "臣妾做不到"
fun(*s) 

在实参的位置上给一个序列,列表,可迭代对象前面加一个*表示把这个序列打散

在形参的位置上的*表示把接收到的参数组和成一个元组

如果是字典,也可以进行打散操作,只不过需要两个*.

def fun(**kwargs):
    print(kwargs)

dic = {'a':1, 'b':2}
fun(**dic)  # **dic: 'a' = 1,'b' = 2 

3.函数的注释

def chi(food, drink):
    """
     这里是函数的注释,先写一下当前这个函数是干什么的,比如我这个函数就是一个吃
    :param food: 参数food是什么意思
    :param drink: 参数drink是什么意思
    :return: 返回的是什么东东
    """
    print(food, drink)
    return "very good"

二.命名空间

1.内置名称空间 --> 存放Python解释器为我们提供的名字,list,tuple,str,int这些都是内置命名空间

2.全局名称空间 --> 我们直接在py文件中,函数外声明的变量都属于全局命名空间

3.局部名称空间 --> 在函数中声明的变量会放在局部命名空间

4.加载顺序:内置命名空间 --> 全局命名空间 --> 局部命名空间(函数被执行的时候)

 取值顺序:局部命名空间 --> 全局命名空间 --> 内置命名空间

a = 10
def func():
    a = 20
    print(a)

func()  # 20
a = 10 # 全局名称空间中的内容

def fn(): # fn也在全局名称空间
    a = 20 # 局部名称空间
    print(a)
def gn():
    print(a)
fn()
gn()

结果:
20
10

作用域:

   (1).全局作用域:内置+全局

   (2).局部作用域:局部(函数被调用)

globals() 查看全局中的内容

locals(): 查看当前作用域中的内容

a = 10
def func():
    a = 40
    b = 20
    def abc():
        print("哈哈")
    print(a, b)     # 这里使用的是局部作用域
    print(globals())    # 打印全局作用域中的内容
    print(locals())     # 打印局部作用域中的内容
func()

三.函数嵌套

函数可以互相嵌套

def outer():
    print("哈哈")
    def inner_1():
        print("呵呵")
        def inner_1_1():
            print("嘻嘻")
        inner_1_1()
        print("吼吼")
    def inner_2():
        print("嘿嘿")
    inner_2()
    inner_1()
outer()

结果:
哈哈
嘿嘿
呵呵
嘻嘻
吼吼

四.global和nonlocal

global:在局部访问全局中的内容

a = 100
def func():
    global a    # 加了个global表示不再局部创建这个变量,而是直接使用全局的a
    a = 28
    print(a)
func()
print(a)

结果:
28
28
a = 10 # 全局变量本身就是不安全的, 不能随意修改, 闭包
def func():
    global a  # 1. 可以把全局中的内容引入到函数内部 , 2. 在全局创建一个变量
    # a = 20
    a += 10 # a = a+10
    print(a)

func()
print(a)

global表示,不在使用局部作用域中的内容,而改用全局中的变量

lst = ["麻花藤", "刘嘉玲", "詹姆斯"]
def func():
    lst.append("马云")    # 对于可变数据类型可以直接进行访问,但是不能改地址说白了就是不能赋值
    print(lst)

func()
print(lst)

结果:
['麻花藤', '刘嘉玲', '詹姆斯', '马云']
['麻花藤', '刘嘉玲', '詹姆斯', '马云']

nonlocal:在局部寻找外层函数中离他最近的那个变量

a = 10
def outer():
    def inner(): # 在inner中改变a的值
        nonlocal a # 寻找外层函数中离他最近的那个变量
        a = 20
    inner()
outer()

结果:
报错

nonlocal只能在局部作用域中,调用父级命名空间中的变量,找不到全局中的变量

a = 10
def func1():
    a = 20
    def func2():
        nonlocal a
        a = 30
        print(a)
    func2()
    print(a)
func1()

结果
加了nonlocal
30
30
不加nonlocal
30
20

 

 

posted @ 2018-08-09 18:04  骑驴老神仙  阅读(192)  评论(0)    收藏  举报