Python函数学习笔记
说明:个人学习笔记,并没有包含全部的知识点,只是觉得重要的知识整理了一下。希望其中自己的一些理解能帮助到他人,共同进步,欢迎交流。
函数的定义与理解
定义函数:
def 函数名(参数1, 参数2, … , 参数n):
函数体
函数实例:
def add(x, y):
return x + y
add(2,3)
结果:5
在上面的例子中并没有规定参数x和y的类型,这是Python和Java的区别。在Python中,变量无类型,只有对象才有类型。
例如:
x = 3
3是整数类型的对象,x好比是一个标签,贴在了3上。作为标签的变量x没有类型一说,它不仅可以贴在整数类型的对象上,还可以贴在其它类型的对象上。
参数和对象的关系与变量和对象的关系一样。在函数中的参数所传的都是对象的引用,而不是对象本身。
关于属性
函数是对象,那么它也有属性。可以使用函数dir()查看对象的属性和方法。
#含有In[] Out[]的代码是在Spyder(Python 3.6)下编写
In [1]: def func():
...: a = 1
...: b = 2
...: return a + b
In [2]: dir(func)
Out[2]:
['__annotations__', '__call__', '__class__', '__closure__',
'__code__', '__defaults__', '__delattr__', '__dict__',
'__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__get__', '__getattribute__', '__globals__',
'__gt__', '__hash__', '__init__', '__init_subclass__',
'__kwdefaults__', '__le__', '__lt__', '__module__',
'__name__', '__ne__', '__new__', '__qualname__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__']
In [3]: func.__name__
Out[3]: 'func'
这里列出了func()这个函数对象的属性和方法,用上下划线开始和结束的属性是特殊属性。所有这些属性,都可以用句点的方式调用。
关于参数
函数名后面括号里的叫“形参”,调用函数时,给函数提供的值叫作“实参”。
形参的作用就是 “传对象引用”,结合下面的例子。
实例:
def add(x): #这里的x是形参
a = 10 #a是变量
return a + x #x就是那个形参作为变量
x = 3 #x是变量
add(x) #这里的x是参数,但是它由前面的变量x传递对象3的引用
关于参数收集
当参数的个数不确定时,使用参数收集来处理参数,使用*arg将参数以元组的形式由arg收集起来,使用**kargs将参数以字典的形式由kargs收集起来,注意需要在传值的时候说明“键”和“值”,arg和kargs只是参数的名称,可以换成其它名称。
函数对象相关知识
1 函数是对象,能够被传递,也能够嵌套。
传递函数实例:
def power_seq(func, seq):
return [func(i) for i in seq]
def pingfang(x):
return x**2
if __name__=="__main__":
num_seq = [1,2,3,4]
r = power_seq(pingfang, num_seq)
print(r)
结果:[1, 4, 9, 16]
2 装饰器
实例:
def foo(fun):
def wrap():
print("start")
fun()
print("end")
print(fun.__name__)
return wrap
@foo
def bar():
print("I am in bar()")
bar()
foo()是装饰器函;bar()是被装饰的函数,作为参数传递给装饰器函数。
3 闭包
问题引入:我们如何在函数外面使用函数里面的变量?
闭包实例:
def foo():
a = 3
def bar():
return a
return bar
f = foo()
print(f())
结果:3
解释:在foo()函数里面有变量a和另一个函数bar(),它们是互不统属的,所以a相对函数bar是自由变量,并且在函数bar()中应用了这个自由变量,这里的函数bar()就是闭包。
闭包是一个函数。它的特点是:
- 定义在另一个函数里面(闭包是嵌套函数,bar()嵌套在foo()里面)
- 引用其所在函数环境的自由变量(bar()引用自由变量a)
思考:为什么要使用闭包?
除了要使用函数里面的变量,有时需要对函数创建多个对象就要用到闭包。
例如:
def parabola(a, b, c):
def para(x):
return a*x**2+b*x+c
return para
p = parabola(2,3,4)
print(p(5))
解释:p = parabola(2,3,4)定义了一个抛物线的函数对象,像这样还可以创建多个抛物线的函数对象(如同类创建实例)。
装饰器本质上就是闭包的一种应用。
4 命名空间相关知识
全局变量和局部变量
全局变量是在整个py文件中声明,全局范围内都可以访问;局部变量是在某个函数中声明的,只能在该函数中调用它。
a = 2
def func():
b = 2
print(b)
解释:a = 2即为全局变量,b = 2在函数体内定义为局部变量。
作用域
作用域是程序中变量与对象存在关联的那段程序。作用域划分为四个层级:
- Local:本地作用域
- Enclosing:嵌套作用域
- Global:全局作用域
- Built-in:内建作用域
Python按照上述作用域从上往下的顺序查找变量。
作用域分为静态作用域和动态作用域,Python的作用域是静态的,意思是Python中变量的作用域由它在程序中的位置决定,在函数体内则是本地作用域,在全局范围内则是全局作用域。注意:变量的作用域在函数、类中才能被改变。
命名空间
命名空间是对作用域的一种特殊的抽象,它包含了处于该作用域内的标识符,且本身也用一个标识符来表示,这样便将一系列在逻辑上相关的标识符用一个标识符组织了起来。
简而言之,命名空间是从所定义的命名到对象的映射集合。不用的命名空间可以同时存在,但彼此相互独立、互不干扰。
命名空间分为:
- 本地命名空间(Function&Class: Local Namespaces)
- 全局命名空间(Module: Global Namespaces)
- 内置命名空间(Buile-in Namespaces)
程序在查询命名空间的时候,按照下面的顺序:
Local Ns -> Global Ns -> Built-in Ns
访问本地命名空间可以使用locals(),访问全局命名空间可以使用globals()
5 几个特殊函数
(1) lambda函数:
lambda arg1, arg2, …, argN : expression using arguments
说明:接收多个变量返回单个表达式的值,lambda函数不能包含命令,包含的表达式不能超过一个。
(2) map函数:
map(func, seq)
说明:func是函数对象,seq是序列对象。将序列对象中的元素从左到右依次取出,进行函数运算,结果依次存在一个列表中。
items = [1,2,3,4,5]
list(map(lambda x : x**2, items))
结果:[1,4,9,16,25]
(3) reduce函数:
reduce(function, sequence[, initial])
说明:将函数按照从左到右的顺序作用于序列上
reduce(lambda x,y : x+y, [1,2,3,4,5])
结果:15
(4) filter函数:
filter(function or None, iterable)
说明:返回序列中使函数为真的元素,若函数为None,则返回序列中布尔值为真的元素
list(filter(lambda c : c!=’i’, ‘qiwsir’))
结果:[‘q’,’w’,’s’,’r’]
(5) zip函数:
zip([iterable, ...])
说明:iterable是可迭代对象,zip将各个对象中对应的元素打包成一个个元组,返回由这些元组组成的对象,可以使用list()来查看对象内容。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以实现解压。
In [1]: a = [1,2,3]
In [2]: b = [4,5,6]
In [3]: zipped = zip(a,b)
In [4]: zipped
Out[4]: <zip at 0xc9747c8>
In [5]: list(zipped)
Out[5]: [(1, 4), (2, 5), (3, 6)]
In [6]: a1, a2 = zip(*zip(a,b))
In [7]: a1
Out[7]: (1, 2, 3)
In [8]: a2
Out[8]: (4, 5, 6)
参考资料:
《跟老齐学Python轻松入门》
Python3菜鸟教程





