一、变量的作用域
根据变量的作用范围把变量分为:局部变量和全局变量。
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点关于这个内存溢出说明:栈不是无限的,它是有限的,过多会导致内存溢出。如图:
三、高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,高阶函数功能就是:把函数本身当做一个参数,传到另一个函数中,然后在这个函数中做处理。