函数(1)

函数语法

函数:

  定义语法: 

def 函数名(参数1,参数2):
    '''注释文档'''
    函数体
    return 

函数定义:

  1. 申请内存空间保存函数体代码
  2. 将上述内存地址绑定函数名
  3. 定义函数不会执行函数体代码,但会检测语法

三种函数定义形式

无参函数:

    def fun():

      函数体

  有参函数:

    def fun(x,y):

      函数体

  空函数:

    def fun():

      pass/...(表示占位符)

例子:

#无参函数:
def fun():
    print("hello")
fun()


#有参函数:
def fun(x, y):
    res = x + y
    return res
add = fun(1, 2)
print(add)


#空函数:
def fun():
    pass

调用函数

  1. 通过函数名找到内存地址
  2. 加括号就是触发函数体代码执行

三种调用形式

  1. 语句形式:只加括号调用函数
  2. 表达式形式
  3. 函数调用可以当参数  
#语句形式
def fun():
    print("hello")
fun()


#表达形式:
def fun(x, y):
    res = x + y
    return res
add = fun(1, 2)
print(add)


#调用函数当参数:
def fun(x, y):
    res = x + y
    return res
add = fun(fun(1, 2), 10)
print(add)

返回值:当函数体执行 return 时表示终止函数运行,并且会将 return 后的值当做本次运行结果返回

1.None:函数体没有return 或者
          return None

          return

2. 返回一个值:return

3.返回多个值: 多个值之间逗号分隔 return 返回元组(这个元组是默认的不能修改)

 

实参与形参

形参:在定义函数时的参数
实参:在调用函数时的参数
形参与实参的关系:

  1. 在调用时实参会绑定形参
  2. 绑定关系只能在函数体内使用
  3. 实参与形参的绑定关系只有调用时生效,而调用结束后则解除绑定关系

实参传值:

# 形式一:
func(1, 2)

# 形式二:
a = 1
b = 2
func(a, b)

# 形式三:
func(int('1'), 2)

形参与实参的使用

  位置参数

    位置形参:在函数定义时,按照从左到右的顺序定义

      特点:必须被传值,形参有几个值,就要传入几个值

    位置实参:调用时按照从左到右的顺序依次传值

      特点:按照形参顺序对应传值

def func(x,y):
    print(x,y)
func(1,2)

关键字参数

  关键字形参:在函数调用时按照 keys 与 value 的形式传值

    特点:根据“变量名”传值且可以不按照顺序传值

def func(x,y):
    print(x,y)

func(y=2,x=1)

位置参数与关键字参数的混合使用:

  1,位置实参必须放在关键字实参前

func(1,y=2)

  2,不能同时给同一个形参传多个值

func(1,y=2,x=3) #错误的演示

默认参数:在定义函数时就已经被赋值的形参

    特点:定义时被赋值了调用时就可以不用赋值,当然也可以在重新赋值

def func(x,y=3):
    print(x,y)


func(x=1,y=44444)#y在形参定义时已经赋值了,但是调用函数时也可以在重新赋值
def register(name,age,gender='男'):
    print(name,age,gender)

register('三炮',18)
register('二炮',19)
register('大炮',19)
register('没炮',19,'女')

位置参数与默认参数的混合使用

  1,位置形参必须在默认形参的左边

def func(y=2,x):
    pass

  2,默认参数的值是在函数定义赋值的,准确的说是赋予了内存地址

m=2
def func(x,y=m): # y=>2的内存地址
    print(x,y
m=3333333333
func(1)

  3,默认值可以指定任意类型,但是不推荐使用可变类型,因为这样会使整个函数的逻辑关系变的混乱。

      函数理想的状态:函数的调用只跟函数本身有关系,不被外界代码影响。

def func(x,y,z,l=None):
    if l is None:
        l=[]
    l.append(x)
    l.append(y)
    l.append(z)
    print(l)

func(1,2,3)
func(4,5,6)

new_l=[111,222]
func(1,2,3,new_l)

可变长参数

可变长度的参数(*与**的用法)
  可变长度指的是在调用函数时,传入的值(实参)的个数不固定
  而实参是用来为形参赋值的,所以对应着,针对溢出的实参必须有对应的形参来接收

可变长度的位置参数
I:*形参名:用来接收溢出的位置实参,溢出的位置实参会被*保存成元组的格式然后赋值紧跟其后的形参名
*后跟的可以是任意名字,但是约定俗成应该是args
def my_sum(*args):
    res=0
    for item in args:
        res+=item
    return res

res=my_sum(1,2,3,4,)
print(res)
 II: *可以用在实参中,实参中带*,先*后的值打散成位置实参
def func(x,y,z):
    print(x,y,z)

# func(*[11,22,33]) # func(11,22,33)
# func(*[11,22]) # func(11,22)

l=[11,22,33]
func(*l)
III: 形参与实参中都带*
def func(x,y,*args): # args=(3,4,5,6)
    print(x,y,args)

func(1,2,[3,4,5,6])
func(1,2,*[3,4,5,6]) # func(1,2,3,4,5,6)
func(*'hello') # func('h','e','l','l','o')
可变长度的关键字参数
I:**形参名:用来接收溢出的关键字实参,**会将溢出的关键字实参保存成字典格式,然后赋值给紧跟其后的形参名
**后跟的可以是任意名字,但是约定俗成应该是kwargs

def func(x,y,**kwargs):
    print(x,y,kwargs)

func(1,y=2,a=1,b=2,c=3)
II: **可以用在实参中(**后跟的只能是字典),实参中带**,先**后的值打散成关键字实参
def func(x,y,z):
    print(x,y,z)

func(*{'x':1,'y':2,'z':3}) # func('x','y','z')
func(**{'x':1,'y':2,'z':3}) # func(x=1,y=2,z=3)
III: 形参与实参中都带**
def func(x, y, **kwargs):
    print(x, y, kwargs)


func(y=222, x=111, a=333, b=444)
func(**{'y': 222, 'x': 111, 'a': 333, 'b': 4444})
混用*与**:*args必须在**kwargs之前

def index(x, y, z):
print('index=>>> ', x, y, z)


def wrapper(*args, **kwargs): # args=(1,) kwargs={'z':3,'y':2}
index(*args, **kwargs)
# index(*(1,),**{'z':3,'y':2})
# index(1,z=3,y=2)


wrapper(1, z=3, y=2)
 

 

命名关键字参数

命名关键字参数:在定义函数时,*后定义的参数,如下所示,称之为命名关键字参数

特点:命名关键字实参必须按照key=value的形式为其传值

def func(x,y,*,a,b): 
    print(x,y)
    print(a,b)

 func(1,2,b=222,a=111)

组合使用

形参混用的顺序:位置新参,默认形参,*args,命名关键字形参,**kwargs

def func(x,y=111,*args,z,**kwargs):
    print(x)
    print(y)
    print(args)
    print(z)
    print(kwargs)

名称空间namespacs:存放名字的地方,对栈区的划分,可以在栈区中存放相同的名字

内置名称空间

存放的名字:python解释器内置名字

存活周期:python解释器启动则产生,python解释器关闭则销毁

全局名称空间

存放的名字:只要不是函数内定义、也不是内置的,剩下的都是全局名称空间的名字

存活周期:python文件执行则产生,python文件运行完毕后销毁

局部名称空间

存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字

存活周期:在调用函数时存活,函数调用完毕后则销毁

input=333

def func():
    input=444
    print(input)

func()

名称空间的加载顺序

内置名称空间>全局名称空间>局部名称空间

销毁顺序

局部名称空间>全局名空间>内置名称空间

查找顺序

名字的查找优先级:当前所在的位置向上一层一层查找

内置名称空间

全局名称空间

局部名称空间

 

如果当前在局部名称空间:局部名称空间—>全局名称空间->内置名称空间

input=333
def func():
    input=444
func()
print(input)

如果当前在全局名称空间:全局名称空间->内置名称空间

input=333
def func():
    input=444
func()
print(input)

作用域

全局作用域:内置名称空间、全局名称空间

1、全局存活:python解释器启动运行代到运行结束的过程

2、全局有效:被所有函数共享

x=111
def foo():
    print(x,id(x))

def bar():
    print(x,id(x))

foo()
bar()

print(x)

局部作用域: 局部名称空间的名字

1、临时存活:函数调用运行代码到调用结束

2、局部有效:函数内有效

如果再局部想要修改全局的名字对应的值(不可变类型),需要用global

x=111

def func():
    global x 
    x=222

func()
print(x)

修改全局的值(可变类型),不用global

l=[111,222]
def func():
    l.append(333)

func()
print(l)

 nonlocal: 修改函数外层函数包含的名字对应的值(不可变类型)

    

函数对象:

1、可以赋值

def func():
  print("111")
f=func print(f,func) f()

2、可以当做函数参数传给另外一个函数

def func():
    print("11")
f=func
print(f,func)
f()
def foo(x):
    x()
foo(func)

3、可以当做函数当做另外一个函数的返回值


def func():
  print("111")
f=func f()
def foo(x):

    return x

res=foo(func)

print(res)

res()

4、可以当做容器类型的一个元素

l=[func,]

# print(l)

l[0]()

 
dic={'k1':func}

print(dic)

dic['k1']()

函数嵌套:

1、函数的嵌套调用:在调用一个函数的过程中又调用其他函数

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


res=max4(1,2,3,4)

print(res)

 

2、函数的嵌套定义:在函数内定义其他函数

def f1():

    def f2():

        pass
posted @ 2020-03-17 22:00  zhw_sylvia  阅读(264)  评论(0)    收藏  举报