目录
一、函数
在python的世界里,函数和我们之前的[1,2,3],'abc',8等一样都是对象,而且函数是最高级的对象(对象是类的实例化,可以调用相应的方法,函数是包含变量对象的对象)
1.1、函数的定义
无论在模块中还是在类中都是使用def关键字来定义一个函数,然而在类中还有很多特殊的函数,并且类中的每个函数的第一个参数都是self(除了静态函数(staticmethod)和类函数(classmethod)等)。
另外,函数内部还可以再定义函数,成为函数的嵌套,被写在内部的函数叫做嵌套函数。详见,闭包和装饰器。
1.2、函数在内存中的存储情况
如图所示变量a,b中存储的地址指向了值8,所以系统打印a或者b的值的时候,就会根据这个地址找到8,然后打印。类似的,当你在变量foo的后面加上()来运行这个函数的时候,系统也会根据变量foo内存储的地址,将函数体内的代码加载到内存中去,然后再执行。因此,也可以将foo赋值给变量bar,只需要执行语句bar = foo即可。
二、函数的参数
1、必需参数
必需参数,必需以正确的顺序传入函数,调用时的数量和声明的时候一致
#必需参数
def info1(age):
print(age)
info1(23)
2、关键字参数
如果你有一些具有许多参数的函数,而你又希望只对其中的一些进行指定,那么你可以通过命名它们来给这些参数赋值。
#关键字参数
def info2(name,age):
print(name,age)
info2(age=23, name='zhuzihan')
3、默认参数
函数在声明是给形参赋默认值。传参时,该形参没有接收到传入实参,则使用默认值。
#默认参数
def info3(age,name='zhuzihan'):
print(name,age)
info3(23,'zzh')
4、不定长参数
不定长的参数传入时可传入元组和字典。一遍在定义函数的时候,使用*args接收元组,**kwargs接收字典。
def add(*args):
print(type(args))#<class 'tuple'>
s = 0
for v in args:
s += v
return s
print(add(1,2,3,4))
def info4(**kwargs):
for i,v in kwargs.items():
print(i,v)
5、参数混合定义
def info4(*args,name='alex',**kwargs):
假如如上所示定义函数,则:
info4(name='zzh',*(23,175),**{'gender':'male','weight':65})
这样传参是不会出现错误
info4(name='alex',23,175,gender='male',weight=65)
这样传参则会提示错误
info4('alex',23,175,gender='male',weight=65)
则会将第一个传入的参数传给name形参。
因此,为避免不必要的错误,所以一般将必需参数或者默认参数等放在最前面,*args需要在**kwargs的前面。并且使用关键字参数的形式传入参数
三、函数返回值
1、函数在执行过程中,只要遇到return语句,就会停止执行,所以也可以将return理解为函数的结束。
2、在python中每个函数都有返回值,没有明确给出返回值的,默认返回None
3、当在函数中返回多个对象,则解释器会将这多个对象装成一个元组返回。
4、在python中,可以将函数名作为返回值。详见:装饰器
def t():
return 1,2,3,'123'
print(t(),type(t()))
输出结果:
(1, 2, 3, '123') <class 'tuple'>
四、变量的作用域
以下内容摘抄https://www.cnblogs.com/fireporsche/p/7813961.html和自己的一些理解
1、全局变量与局部变量
全局变量在全局范围内起作用,局部变量仅在函数内部起作用。在Python中并不是所有的语句块中都会产生作用域。只有当变量在Module(模块)、Class(类)、def(函数)中定义的时候,才会有作用域的概念。
变量名解析:在一个模块(在一个py文件中)在类和函数中可以定义局部变量,并且python在寻找变量的时候,首先寻找的是“最局部的变量”。在一般情况下,函数中的变量相对于模块来讲,是局部变量,模块中的变量相对于整个项目来讲是局部变量,python中的内置变量,所有的模块都能访问,应该是“最全局”的变量了。
注意:我在学习python的过程中,有一个不算弯的弯,一下子没反应过来。在下面代码中的lis在整个模块中也是一个在模块任何地方都能访问的变量。
def add():
s = 0
for value in lis:
s += value
return s
if __name__ == '__main__':
lis = [1,2,3,4]
print(add())
2、作用域类型
在Python中,使用一个变量时并不严格要求需要预先声明它,但是在真正使用它之前,它必须被绑定到某个内存对象(被定义、赋值);这种变量名的绑定将在当前作用域中引入新的变量,同时屏蔽外层作用域中的同名变量。
2.1、L(local)局部作用域
局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。
局部变量域就像一个栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。
2.2、E(enclosing)嵌套作用域
E也包含在def关键字中,E和L是相对的,E相对于更上层的函数而言也是L。与L的区别在于,对一个函数而言,L是定义在此函数内部的局部作用域,而E是定义在此函数的上一层父级函数的局部作用域。主要是为了实现Python的闭包,而增加的实现。
2.3、G(global)全局作用域
即在模块层次中定义的变量,每一个模块都是一个全局作用域。也就是说,在模块文件顶层声明的变量具有全局作用域,从外部开来,模块的全局变量就是一个模块对象的属性。
注意:全局作用域的作用范围仅限于单个模块文件内。
2.4、B(built-in)内置作用域
系统内固定模块里定义的变量,如预定义在builtin 模块内的变量。
以上内容摘抄https://www.cnblogs.com/fireporsche/p/7813961.html和自己的一些理解
3、global和nonlocal关键字
3.1、global关键字
1. 在一个模块中,函数要操作模块中的全局变量,不可直接修改。需要使用global关键字,在函数中声明
x = 100
def func():
global x
print(x)
x = 2
print(x)
func()
print(x)
2.在函数里面声明一个全局变量
def fun(x):
global a
a = x +2
return a
fun(3)
print(a)
3.2、nonlocal关键字
nonlocl用于闭包中,nonlocal就是在闭包中怎样对上一层函数内的变量进行更改。
x = 123
def outer():
x = 100
def inter():
nonlocal x
x = x + 1
print(x)
return inter()
outer()
print(x)
输出结果:
101
123
3.3、locals()函数
locals():会以字典类型返回当前位置的全部局部变量
def runoob(arg): # 两个局部变量:arg、z
z = 1
print (locals())
runoob(4)
输出结果:
{'z': 1, 'arg': 4}
3.4、example
x = int(2.9)
v_out = 10
def outer():
global v_out
global v_outer
v_outer2 = 20
v_outer = 10
print("v_outer in outer %d"%v_outer)
def inner():
global v_inner
nonlocal v_outer2
v_outer=5
v_inner = 5
v_outer2 = 5
print("v_outer in inner %d"%v_outer)
print("v_out in inner %d"%v_out)
print("v_inner in inner %d"%v_inner)
print("v_outer2 in inner %d"%v_outer2)
inner()
print("v_inner in outer %d"%v_inner)
outer()
print("v_outer in global %d"%v_outer)
print("v_inner in global %d"%v_inner)
输出结果:
v_outer in outer 10
v_outer in inner 5
v_out in inner 10
v_inner in inner 5
v_outer2 in inner 5
v_inner in outer 5
v_outer in global 10
v_inner in global 5
四、递归函数(实例)
自己调用自己。
1、阶乘
def factorial(n):
n = int(n)
if n > 1:
return factorial(n-1)*n
else:
return 1
print(factorial(5))
2、斐波那契数列
取出斐波那契数列中第n个数字。
def fibo(n):
if n > 2:
num = fibo(n-1)+fibo(n-2)
return num
elif n==2:#下面两条语句是规定前两个数字是0和1
return 1
else:
return 0;
print(fibo(6))
五、重要的内置函数
1、filter()
根据传入的函数,将str中的每一个元素依次使用function判定,为True则返回,否则丢弃
s1 = ['a', 'b','c', 'd']
def fun1(s):
if s != 'a':
return s
#根据传入的函数,将str中的每一个元素依次使用function判定,为True则返回,否则丢弃
ret = filter(fun1, s1)
print(type(ret),list(ret))# ret是一个迭代器对象
输出结果:
<class 'filter'> ['b', 'c', 'd']
2、map()
对sequence中的item依次执行function(item),将执行结果组成一个map object迭代器返回.map也支持多个sequence,这就要求function也支持相应数量的参数输入。
s1 = [1, 2,'a', 'b']
def fun2(s):
s = str(s)
return s + "alvin"
ret = map(fun2, s1)
print(type(ret),ret) # map object的迭代器
print(list(ret))
输出结果:
['aalvin', 'balvin', 'calvin', 'dalvin']
3、reduce()
from functools import reduce
def add1(x,y):
return x + y
print (reduce(add1, range(1, 10)))##(注:1+2+...+9)
print (reduce(add1, range(1, 10), 20))## (注:1+2+...+9+20)
输出结果:
45
65
4、lambda : 匿名函数
lambda 传入的参数:函数体
#普通函数
def add(a,b):
return a + b
print(add(2,3))
#匿名函数
add = lambda a,b : a + b
print(add(2,3))
输出结果:
5
5
5、综合实例
from functools import reduce
print(reduce(lambda x,y:x*y,range(1,5)))#依次从列表中取出1,2,3,4做积。即1*2=2 2*3=6 6*4=24
seq = map(lambda x:x*x,range(1,5))#将[1,2,3,4]中的元素依次取出来,平方后,放到列表中
print(list(seq))
输出结果:
24
[1, 4, 9, 16]
第一遍学习python。跟以前学习的语言有很多不同。特别是细节方面,python的很多方面都令我折(wu)服(nai)。以上整理的笔记,有缘人若发现错误或者表述不贴切的地方,万望指出。小弟于此先行谢过。