Python3 函数嵌套与递归

函数的变量:
函数的变量可以分为局部变量,全局变量
局部变量只能在某个函数中使用
全局变量可以在整个程序中使用

如何定义局部和全局变量?
定义变量的时候开头没有缩进就是全局变量
局部变量是在函数块里面定义的

函数块在调用变量的时候,如果全局变量和局部变量相同,优先调用局部变量

name="chenchaozhen"
def pr():
    name="children"
    print("my name is ",name)
pr()

运行结果;
my name is children

如何在函数块里面定义全局变量?

name="chenchaozhen"
def pr():
    global name
    name="children"
    print("my name is ",name)
pr()
print(name)

运行结果:
my name is children
children

  ##第一个全局name变量被第二个全局name变量覆盖了,代码执行到的时候才会更改

name="chenchaozhen"
def pr1():
    print("my name is ",name)
def pr2():
    global name  #声明name是全局变量
    name="chen da zhen" #更改name,更改的是全局变量 而不是局部变量
    print("my name is ",name)

pr2()
pr1()

运行结果:
my name is chen da zhen
my name is chen da zhen

pr1()
pr2()
运行结果:
my name is chenchaozhen
my name is chen da zhen

所以执行到代码的时候 global 才会生效
如果函数内容无global 关键字,优先读取局部变量再读取全局变量,无法重新赋值给全局变量,但是当全局变量是可变类型(列表,字典)的时候,可以追加
如果函数中有global 关键字,表示函数内的局部变量本质上就是全局变量,可以读取赋值

当全局变量是可变类型(列表,字典)的时候,可以追加

name=["chen","chao"]
def pr1():
    name.append("zhen")
    print(name)
    del name[0]
    print(name)
    name.insert(1,"chen chao zhen")
    print(name)
pr1()


运行结果:
['chen', 'chao', 'zhen']
['chao', 'zhen']
['chao', 'chen chao zhen', 'zhen']
所以确定全局变量如果是可变类型的话,可以追加或者删除

但是要注意,赋值变量和声明变量不能相反,不然会报错

name=["chen","chao"]
def pr1():
    name="aa"
    global name
    print(name)
pr1()

运行结果:
"E:\Python Project\venv\Scripts\python.exe" "E:/Python Project/day3/s4.py"
File "E:/Python Project/day3/s4.py", line 4
global name
^
SyntaxError: name 'name' is assigned to before global declaration

函数里面也可以嵌套函数,先从外层运行,遇到函数,编译不执行,然后调用的时候再执行

执行顺序:从外到内 从上到下

def chen():
    2name="chen"
    2print(name)
    def chao():
        3name="chao"
        3print(name)
        def zhen():
            4name="zhen"
            4print(name)
        3print(name)
        3zhen()
    2chao()
1chen()

运行结果:

chen
chao
chao
zhen

name="chen"
def  test():
    name="abb"
    def testtest():
        global name
        name="xbb"
    testtest()
    print(name)
print(name)
test()
print(name)

#先执行print(name)
#再执行test()
#最后执行print(name)
运行结果:
chen
abb
xbb

notlocal 指的是函数的上级变量,不像global 直接指的是最上级的全局变量

前向引用:

def foo():
    print("this foo")
    bar()
def bar():
    print("this bar")

foo()

运行结果:
this foo
this bar

def bar():
    print("this bar")
def foo():
    print("this foo")
    bar()

foo()

运行结果:

this foo
this bar

为什么bar函数在前面,foo()也能调用呢?
因为代码运行是从上到下执行的,所以在开始的时候已经编译了bar()函数,所以要执行bar()函数的时候,内存里面已经有了,就能正常调用了

def foo():
    print("this foo")
    bar()
foo()

def bar():
    print("this bar")

什么叫函数的递

这样就无法运行了,会有报错:
运行结果:
NameError: name 'bar' is not defined
this foo


函数及变量,函数的存储方式就像变量一样,运行到函数的时候会编译存储到内存里面,分配内存空间,然后调用函数的时候直接去内存空间读取

归?

在函数内部,可以调用其他函数。如果在调用一个函数的过程中直接或间接调用自身本身这就是递归

def calc(n):
    print(n)
    if int(n / 2) == 0:
        return n
    res=calc(int(n / 2))
    return res
res=calc(10)
print(res)

运行结果:
10
5
2
1
1

递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
例子二:

list=["chen","chao","zhen","xu","zhen","zhi"]
def find_way(list):
    if len(list)==0:
        return "查无此人"
    name=list.pop(0)
    if name=="xu":
        return "找到了"
    print("这里没找到,%s 不是我们要找的,我们继续往%s下找" %(name,list))
    find=find_way(list)
    return find
check=find_way(list)
print(check)

运行结果:
这里没找到,chen 不是我们要找的,我们继续往['chao', 'zhen', 'xu', 'zhen', 'zhi']下找
这里没找到,chao 不是我们要找的,我们继续往['zhen', 'xu', 'zhen', 'zhi']下找
这里没找到,zhen 不是我们要找的,我们继续往['xu', 'zhen', 'zhi']下找
找到了

#函数名就相当于一个内存地址,即函数即变量

def name():
    print("aaa")
print(name)

运行结果:
<function name at 0x00000000021F0A60>

def test1():
    print('in the test1')
def test():
     print('in the test')
     return test1

print(test)
res=test()
print(res()) #相当于执行test1()这个函数了,因为test1这个函数的内存位置赋值给了res,所以res相当于test1函数的别名

运行结果:

<function test at 0x0000000001E90D90>
in the test
in the test1
None

#函数的作用域只跟函数声明时定义的作用域有关,跟函数的调用位置无任何关系
#优先找定义的作用域里面的变量,如果找不到就往上层找,如果找不到,一直找到最上层位置

name = 'alex'
def foo():
    name='linhaifeng'
    def bar():
        # name='wupeiqi'
        print(name)
    return bar
a=foo()
print(a)
a() #bar()

运行结果:

<function foo.<locals>.bar at 0x0000000001E80D90>
linhaifeng

name='alex'
def foo():
    name='lhf'
    def bar():
        name='wupeiqi'
        def tt():
            print(name)
        return tt
    return bar
bar=foo() # return bar 返回bar这个函数的内存值
tt=bar() #调用bar这个函数,return tt 返回tt这个函数的内存值
print(tt) #打印tt这个函数的内存制
tt() #调用tt这个函数
foo()()() #括号按顺序代表函数,第一个代表foo,第二个代表bar,第三个代表tt
#亦可以理解,foo()作为第一层运行函数,因为foo()会有返回值,所以foo()的返回值加上()组成第二层运行的函数,第三层道理是是一样的

运行结果:

<function foo.<locals>.bar.<locals>.tt at 0x0000000002710E18>
wupeiqi
wupeiqi

猜你喜欢

转载自www.cnblogs.com/children92/p/9167282.html
今日推荐