函数的变量:
函数的变量可以分为局部变量,全局变量
局部变量只能在某个函数中使用
全局变量可以在整个程序中使用
如何定义局部和全局变量?
定义变量的时候开头没有缩进就是全局变量
局部变量是在函数块里面定义的
函数块在调用变量的时候,如果全局变量和局部变量相同,优先调用局部变量
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