函数风云序列之函数初现

函数

一、定义函数:

def + 关键​字(函数名,一个变量,遵循变量命名的规则) + ( 参数 )  : 

    (缩进)          函数体(代码块)​

函数名的本质(就是这个函数所在的内存地址)像这样的就是叫第一类对象:​

1. 函数名是不可以变得,函数名赋值只是分享内存地址,这个函数本身的名字是不会变的,还是原来定义时的名字

def func():
    pass
f = func
print(func)
print(f)

两次运行结果:

<function func at 0x00000000003E1E18>
<function func at 0x00000000003E1E18>

2. 函数名可以赋值:

   函数名指向的是这个函数的内存地址,当把这个函数名赋值给另一个变量名,两个变量都指向函数内存地址,所以用两个变量都可以调用这一个函数内存地址,即可以调用这个函数.

def func():
    print(1)
f = func             #赋值,令f() = func()
f()

3.函数名可以作为容器类型中的一项,可以做字典的键.

def lst():
     return 1,2 ,3 ,4 ,5
lsit = [*lst()]
print(lsit)

4.函数名可以作为另一个函数的参数.

def login():
    print('欢迎登陆')
def index(auth):
    auth()               #函数名的赋值,令auth = login,即autn() = login()
    print('欢迎来到首页')
index(login)

5.函数可以作为另一个函数的返回值​​

def login_failed():
    print('登录失败')
def index():
    print('欢迎来到首页')
def login(uer,pwd):
    if uer == 'alex'and pwd == 'sb':
        return index                  #返回index()函数的print
    else:
        return login_failed           #返回login_failed()的print
res_func = login('alex','ssb')
res_func()

二、调用函数:

 本质是函数的内存地址加括号 ,所以函数名可以进行赋值,谁调用返回值就给谁。

三、关键字()参数)​

print(关键字)        #输出函数的内存地址类似于 <function f at 0x00000000003C1E18> 这样子的 

函数值:​ 返回return                 #函数返回值      ,

  1.没有返回值就默认返回None(即使没有写return)

    2.当程序运行碰到return时,就结束函数

  3.当返回一个值的时候就是本身的数据类型,返回多个的时候就是元组形式返回。

1.函数的参数:

1.形参:在定义函数的时候使用​

A.位置参数:按照实参的位置把对应的值赋值给形参中的变量

B.关键字参数:​

也叫默认参数:在定义形参的时候,给变量进行赋值.后面使用的时候不用写入实参.若写实参,便重新赋值,使用实参的值.​

C.混合参数:​

即括号里既有位置参数也有关键字参数,这时位置参数应该在前面,默认参数在后面

2.实参: 在调用的时候使用​

A.位置参数:按照位置给形参进行传参

B.关键字参数:​

也叫默认参数:按照关键字给形参进行传参

C.混合参数:​

即括号里既有位置参数也有关键字参数,这时位置参数应该在前面,默认参数在后面 ​ 

3.传参:实参与形参在括号里是一一对应的过程就是传参

2.函数参数进阶

1.动态位置参数: * + 位置参数            #惯用(*agrs),获取的数据是一个元组,位置参数在动态位置参数前面 :位置参数 > 动态位置参数​​​

2.动态关键字参数: ** + 关键字参数​​   #惯用(**kwagrs),动态关键字传参获取的是一个字典,每个默认参数都是一个键值对,关键

字参数在动态关键字参数前面: 关键字参数 > 动态关键字参数

#动态位置参数    最后获得的是以一个元组的形式输出

def eat(a,b,*food):             #( * + 位置参数 )就是动态位置参数
    print('我今天想吃',a,b,food)

eat('回锅肉','卫龙','百威','馒头','榨菜')
#动态关键字参数     最后获取的数据是一个字典
def eat(**food):              # (** + 关键字参数) 是默认关键字参数
    print('我今天想吃',food)
eat(food=1,a=2,b=3)

#混合参数  推荐这么写 位置参数>动态位置参数>默认参数>动态默认参数
def func1(a,*args,b=1,**kwargs):
    print(a,b,args,kwargs)

def func2(a,*agrs,**kwargs,b=1):         #不可以这样子用
     print(a, b, agrs, kwargs)
func1(a,b,args,kwargs)

总的位置关系是:

位置参数 > 动态位置参数 > 关键字参数 > 动态关键字参数

推荐写法:

def func1(a,*agrs,b=1,**kwargs):

print(a, b, agrs, kwargs)​

 

3.解包与打包:

lst = [1,2,3,4]                                                      #运行顺序:

def func(*args):             #聚合 (1,2,3,4)                                 2

print(*args)                 #在解包 1,2,3,4                                  3

func(*lst)                   # * 是按顺序解包相当于func(1,2,3,4)​​                1
dic = {'name':'alex','age':15}
def func(**kwagrs):
    print(kwagrs)
func(**dic)

4.三元运算符:

def f (a,b):

l = (a if a >b else b)    #三元运算符的表示方法

return l 

print(f(3,5))

​            a              if a >b         else                b

语法: 结果​ 如果条件成立就是用前面的,如果条件不成立就是用后面的结果​

四、函数的嵌套

注意不能出现死循环嵌套函数:

def fun2():
    print(222)
    def fun3():
        print(666)
    print(444)
    fun3()
    print(888)
print(33)
fun2()
print(555)

#错误嵌套:  不能循环嵌套

def f1():
    print(1)
    f3()
def f2():
    print(2)
    f1()
def f3():
    print(3)
    f2()
f3()

 

五、名称空间

1.命名空间的定义

我们给存放名字和值的关系的空间起一个名字叫: 命名空间. 我们的变量在存储的时候就 是存储在这片空间中的.   

命名空间分类:         

      1. 全局命名空间--> 我们直接在py文件中, 函数外声明的变量都属于全局命名空间:作用于全局和局部作用域,加载在运行代码之后       

      2. 局部命名空间--> 在函数中声明的变量会放在局部命名空间 :作用于局部作用域,加载于调用之后      

      3. 内置命名空间--> 存放python解释器为我们提供的名字,内置函数、list、tuple、str、int等这些都是内置命名空间:作用于全局作用域,加载于运行之后,代码之前

​查找顺序: 局部空间 > 全局空间 > 内置空间​ 

​加载顺序:内置空间 > 全局空间 > 局部空间

内置函数: pytharm中自带的函数,可以直接调用的函数​​

2.作用域:

2.1全局作用域:全局和内置空间

.globals() 查看全局作用域的变量和内容​

2.2局部作用域: 函数局部空间

.locals() 查看局部作用域内的变量和内容​

#查看变量内容
a = 5
def func():
    b = 3
    print(b)
    print(locals())          #查看局部变量与内容
func()
print(globals())             #查看全局变量与内容

六、globalnonlocal

1.global关键字适用于在全局作用域中

首先我们写这样一个代码,首先在全局声明一个变量,然后再局部调用这个变量,并改变这个变量的值 

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

通过新建一个内存地址,改变变量指向来改变全局变量的内容,可变数据类型在局部可以进行直接更改,不可变的数据类型需要利用global新建一个内存地址,然后让改数据改变指向到这个新地址

例:

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

2. nonlocal适用于局部作用域

nonlocal 表示在局部作用域中,改变离他最近的父集变量的值,调用父级命名空间中的变量。 

改变离他最近的存在于局部作用域中的父集的变量:

   A.func1的变量,若func1()下没有变量,则不改变,在func1()上面就是全局作用域了

  B.func2与func1之间还有一层嵌套,则改变中间这一层的变量,说白了就是离他最近的有改变量的父集

a = 10
def func1():   
    a = 20   
    def func2():
        nonlocal a  #改变离他最近的父集的变量,即func1的变量,若func1()下没有 变量,则不改变,若func2与func1之间还有一层嵌套,则改变中间这一层的变量,说白了就 是离他最近的有改变量的父集                 
a = 30
print(a) func2() print(a) func1()

结果:

加了nonlocal

30

30

不加nonlocal

30

20    

 

posted @ 2018-11-01 17:18  三藏大师3  阅读(127)  评论(0编辑  收藏  举报