一、变量的作用域
根据变量的作用范围把变量分为:局部变量和全局变量。
def test(name,age,**kwargs):
print(name)
print(age)
print(kwargs)
test_1("test")
def test_1(source):
print("from %s"%source)
test("bianbian",age=18,sex="girl",love="peng")
结果:
bianbian
18
{'sex': 'girl', 'love': 'peng'}
from test
test_1函数之后执行,没有问题;如果test_1函数之前执行会报错,因为test_1函数还没有被读到内存中,所以报错。
def test(name,age,**kwargs):
print(name)
print(age)
print(kwargs)
test_1("test")
test("bianbian",age=18,sex="girl",love="peng")
def test_1(source):
print("from %s"%source)
结果:
bianbian
18
{'sex': 'girl', 'love': 'peng'}
Traceback (most recent call last):
File "/Users/bianbian/PycharmProjects/test/test6.py", line 6, in <module>
test("bianbian",age=18,sex="girl",love="peng")
File "/Users/bianbian/PycharmProjects/test/test6.py", line 5, in test
test_1("test")
NameError: name 'test_1' is not defined
1、局部变量
指在局部生效,定义在函数体内的变量只能在函数里面生效,这个函数就是这个变量的作用域。
def test(name):
print("before change:", name)
name="pengpeng"
print("after change:", name)
name="bian"
print("------调用test------")
test(name)
print("------打印name------")
print(name)
结果:
------调用test------
before change: bian
after change: pengpeng #局部变量生效
------打印name------
bian
2、全局变量
在整个程序中都生效的变量,在整个代码的顶层声明。
love="pengpeng" # 定义全局变量
def test_1():
print("love", love)
def test_2():
love="shen"
print("love", love)
print("------test_1------")
test_1()
print("------test_2------")
test_2()
print("------打印love------")
print("love", love)
结果:
------test_1------
love pengpeng #打印的是全局变量
------test_2------
love shen #打印局部变量
------打印love------
love pengpeng #打印全局变量
全局变量的优先级是低于局部变量的,当函数体内没有局部变量,才会去找全局变量。
3、修改变量作用域
(1)函数里面修改全局变量
现在global先声明一下全局变量,然后在函数中全局变量重新赋值
love="pengpeng" # 定义全局变量
def test_1():
print("love", love)
def test_2():
global love
love="shen"
print("love", love)
print("------test_1------")
test_1()
print("------test_2------")
test_2()
print("------打印love------")
print("love", love)
结果:
------test_1------
love pengpeng
------test_2------
love shen
------打印love------
love shen
(2)只在函数里面声明全局变量
love="pengpeng" # 定义全局变量
def test_1():
global love
love="shen"
print("love", love)
print("------test_1------")
test_1()
print("------打印love------")
print("love", love)
结果:
------test_1------
love shen
------打印love------
love shen
最好不要用global这个关键字,防止别人串改自己的代码。
(3)修改列表
love =['bianbian',"pengpeng"] # 定义一个列表
def test_1():
love[0]="shen"
print(love)
print("------test_1------")
test_1()
print("------打印love------")
print(love)
结果:
------test_1------
['shen', 'pengpeng'] #函数内的names输出
------打印love------
['shen', 'pengpeng'] #函数外的names输出
列表love被当做在函数中全局变量,重新赋值了,是可以被修改的。
(4)小节
- 只有字符串和整数是不可以被修改的,如果修改,需要在函数里面声明global。
- 但是复杂的数据类型,像列表(list)、字典(dict)、集合(set),包括我们后面即将要学的类(class)都是可以修改的。
3、作用域小结
- 在子程序(函数)中定义的变量称为局部变量,在程序一开始定义的变量称为全局变量。
- 全局变量的作用域是整个程序,局部变量的作用域是定义该变量的子程序(函数)。
- 当全局变量和局部变量同名时:在定义局部变量的子程序内,局部变量起作用;在其他地方,全局变量起作用。
二、递归
1、定义
一个函数在内部调用自身,这个函数被称为递归函数。
def test(n):
print(n)
if int(n/2) == 0:#结束符
return n
return test(int(n/2)) #调用函数自身
a = test(10)
结果:
10
5
2
1
根据代码,最后一层,一定需要一个结束符,来结束。
def test(n):
if n == 0:
return n
return n+test(n-1)
n=test(100)
print(n)
结果:
5050
test(n-1)返回的是(n-1)+test(n-2)......
2、递归特性总结
- 必须要有一个明确的结束条件。
- 每次进入更深一层的递归时,问题规模相比上次递归都应该少(问题规模:比如你第1次传进的是10,第2次递归应该是9...依次越来越少,不能越来越多)。
- 递归的效率不高,递归层次过多会导致内存溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈贞,每当函数返回,栈就会减一层栈贞。由于栈的大小不是无限的,所以递归的次数过多,会导致栈溢出)。
第3点关于这个内存溢出说明:栈不是无限的,它是有限的,过多会导致内存溢出。如图:
三、高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,高阶函数功能就是:把函数本身当做一个参数,传到另一个函数中,然后在这个函数中做处理。