一、上节回顾:

1、文件的修改操作、删除操作、with 语句

   函数:函数的定义:def 函数名(形参1,形参2.。。。)

   函数的调用:函数名(实参1,实参2)

   函数的返回值:

            定义阶段:return

         三种情况:没有返回值,返回一个值,返回多个值

          调用阶段:接收返回值,变量=函数名()

函数的参数:

  形参:(定义阶段)

      位置参数

      默认参数(关键字参数)

  实参:(调用阶段)

     按照位置传参数

         按照关键字传参数

二、作业讲解:

1、

# # 写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,
# # 并将其作为新列表返回给调用者
def func1(l):
    new_1=l[1::2]
    return new_1
# ret=func1([1,2,3,4,5])
# print(ret)

2、# 写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5

def func2(l):
    return len(l)>5
ret=func2([1,"dfdg",32,35,56,7,])
print(ret)     #True

3、

# 写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,
# 并将新内容返回给调用者。

# 第一种方法:
def func3(l):
    if len(l)>2:
        return l[:2]
    else:return l
# 第二种方法
 def func3(l):return l[:2]

 4、

# 写函数,检查用户传入的对象(字符串、列表、元组)
# 的每一个元素是否含有空内容,并返回结果。
def func8(s_l_t):
    for i in s_l_t:
        if not i and i !=0 and i !=False:
            return True
        else: return False

5、

# 写函数,检查传入字典的每一个value的长度,如果大于2,
# 那么仅保留前两个长度的内容,并将新内容返回给调用者。
#PS:字典中的value只能是字符串或列表
# 第一种方法
def func6(dic):
    for k in dic:
        value=dic[k]
        if len(value)>2:
            dic[k]=value[:2]
    return dic
# 第二种方法
def func7(dic):
    for k in dic:
        dic[k]=dic[k][:2]
    return dic

6、

# 写函数,接收两个数字参数,返回比较大的那个数字。
# 方法一
def func9(a,b):
    if a>b:
        return a
    else:return b
print(func9(1,2))
# 方法二(三元运算符)
c=a if a>b else b

三、今日内容

(一)参数

(1)位置参数

(2)默认参数

(3)动态参数

1、动态参数    

 def func(*args)      #在参数面前加个*,这个参数就是动态参数了,
  print(args)              使用的时候,所有接收过来的参数都被组织成一个元组的形式

 

2、位置参数和动态参数相结合,动态参数必须写在位置参数的后面          

def func(a,b,c,*args):
    print(a,b,c)
    print(args)
ret=func(1,2,3,"sxfsd",{1213})
print()
# 1 2 3
# ('sxfsd', {1213})

3、默认参数,

  (1)只传前面三个的时候    

def func(a,b,c,key="key",*args):
    print(a,b,c)
    print(key)
    print(args)

ret=func(1,2,3,)
print()
#1 2 3
# key
# ()

  (2)传全部的时候

def func(a,b,c,key="key",*args):
    print(a,b,c)
    print(key)
    print(args)
ret=func(1,2,3,"sxfsd",1,2,{1213})
print()
# 1 2 3
# sxfsd
# (1, 2, {1213})

4、关键字参数

  按照顺序: 位置参数 - 动态参数 - 默认参数-  关键字参数

def func(a,*args,key="key",**kwargs):
    print("a:",a)
    print("args:",args)
    print("key:",key)
    print("kwargs:",kwargs)
ret=func(1,2,3,"sxfsd",1,{1213},q="haohao",qq="dajia")
# a: 1
# args: (2, 3, 'sxfsd', 1, {1213})
# key: key
# kwargs: {'q': 'haohao', 'qq': 'dajia'}

5、例子:动态参数的例子   求和

def my_sum(*args):
    sum_2=0
    for i in args:
        sum_2+=i
    return  sum_2
ret=my_sum(1,2,33,44)
print(ret)         #80
ret1=my_sum(11,22,33)
print(ret1)         #66

6、魔性用法,打散列表

def my_sum(*args):     #聚合
    print(args)
l=[1,2,234,546]
ret2=my_sum(l)         #([1, 2, 234, 546],)
ret=my_sum(l[0],l[1],l[2],l[3])    #(1, 2, 234, 546)
ret1=my_sum(*l)          #(1, 2, 234, 546)   按顺序打散

7、只有作为实参和形参才可以加**

def func(**kwargs):
    print(kwargs)
func(d=2,g=3)         #{'d': 2, 'g': 3}
dic={'a':1,"b":2}
func(**dic)           #{'a': 1, 'b': 2}

8、总结:

      (1)动态参数:   args  :接收所有按照位置传的参数,接收到的是参数组成的元组

            **kwargs :接收所有按照关键字传的参数,接收到的是参数组成的字典

      (2) 所有的参数的顺序:位置参数,*args,默认参数,**kwargs

  (3)魔性的用法:

      在调用函数的时候可以打散:  *l   **dic

(二)命名空间

 namespace  命名空间,名称空间

               (1)局部命名空间:每一个函数都有自己的命名空间

      (2)全局命名空间:写在函数外面的变量名

     (3)内置命名空间:python解释器启动之后可以使用的名字

 python 解释器运行起来的加载顺序:

      先所有内置命名空间的中的名字————然后按照顺序加载全局命名空间中的名字

                   局部命名空间中的名字,在调用函数的时候产生,并且随着调用的结束而消失

1、函数的嵌套调用   从全局调用局部 (启动顺序)

def func2():
    print("in func2 now")
    print("多些一行")
    if True:
        print("又多些一行")
    return "func2的返回值"
def func():
    ret=func2()
    print(ret)
    n=20
    print(n)
func()
#in func2 now
# 多些一行
# 又多些一行
# func2的返回值
# 20

2、函数的嵌套定义  在全局命名空间不能调用局部命名空间:

结果是无法调用

3、加载顺序造成的问题

def func():
    print(1)
def func():
    print(2)
func()
# 2
def len(x):
    print("*****%s*****"%x)
len("123")
#*****123*****

4、作用域是指的一个名字可以使用的区域

    局部作用域指向 全局作用域

n=0
def func1():
    def func2():
        print(n)
    func2()
func1()
#0

5、总结:

  作用域:一个名字可以使用的区域

 全局作用域:内置名字空间和全局名字空间中的名字都属于全局作用域

局部作用域:局部名字空间中的名字属于局部作用域

局部作用遇到:可以使用全局作用域中的变量

                       而全局作用域不能使用局部作用域中的变量

                       局部作用域还可以嵌套更小的局部作用域

作用域链:小范围作用域可以使用大范围的变量,但是作用域链是单向的,不能反向应用

 

6、func 的定义 以及调用

     作用域链

n=0
def func1():
    n=1
    def func2():
        n=2
        def func3():
            n=3
            print(n)
        func3()
    func2()
func1()
# 3

7、globals()   保存了在全局作用域中的名字和值

     locals()    中的内容会根据执行的位置来决定作用域中的内容

   如果在全局中执行  两者的打印结果是一致的

def func():
    a=10
    b=20
    print(locals())    #保存了当前作用域中的变量
    print(globals())
n=10
m=22
print(globals())         #保存了在全局作用域中的名字和值
func()

8、函数的嵌套调用和函数的嵌套定义

命名空间:三种:内置 全局  局部

作用域:两张:全局  局部

作用域链:名字的使用  是从小到大范围的就近事件

 9、 小范围可以使用大范围的,但是不能修改

   如果想修改,可以使用global关键字 ——尽量避免使用

n=1
def func():
    global n
    n+=1
func()
print(n)
#2

这个global  使用的是全局的变量  改变了最外面的n的值

10、nonlocal  就近原则(使用上一级变量n),不会改变全局的变量(两层使用)

n=5
def func():
    n=1
    def func2():
        nonlocal n
        n+=1
    func2()
    print(n)      
func()
print(n)
#2
#5

11、总结:

      global 和locals方法

  小范围可以使用大范围 但是不能修改

        如果想修改全局的,使用global关键字----尽量避免

        如果想修改最近拥有该变量的外层函数的:使用nonlocal----不影响全局

(三)函数的名字

1、函数可以赋值

# 函数的名字
def func():
    print("in func")
    return 10
print(func)  #<function func at 0x0000000002082EA0>
f=func          
print(f)        #<function func at 0x0000000002082EA0>
t=func
print(t)        #<function func at 0x0000000002082EA0>
print(t())        #in func   #10
print(f())         #in func   #10
print(func())       #in func   #10

2、总结:

第一类对象的概念

函数名可以赋值

可以作为一个数据结构的元素

可以作为一个函数的参数

可以作为一个函数的返回值