作者:yangwei的马甲 | 来源:互联网 | 2023-08-17 17:50
函数的变量:函数的变量可以分为局部变量,全局变量局部变量只能在某个函数中使用全局变量可以在整个程序中使用如何定义局部和全局变量?定义变量的时候开头没有缩进就是全局变量局部变量是在函数块里面定义的
函数的变量:
函数的变量可以分为局部变量,全局变量
局部变量只能在某个函数中使用
全局变量可以在整个程序中使用
如何定义局部和全局变量?
定义变量的时候开头没有缩进就是全局变量
局部变量是在函数块里面定义的
函数块在调用变量的时候,如果全局变量和局部变量相同,优先调用局部变量
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)
运行结果:
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函数的别名
运行结果:
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()
运行结果:
.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()的返回值加上()组成第二层运行的函数,第三层道理是是一样的
运行结果:
.bar..tt at 0x0000000002710E18>
wupeiqi
wupeiqi