今天学习函数的最后一节。一般来说,前面三节的语法知识已经够用了,这一篇是几个高级一点的话题,主要包括递归函数、匿名函数、函数的属性与标注。由于是高级话题,我们就简单的介绍。
啥?前三节是啥?好吧。
不记得的童鞋点下面快速回顾一下!
python的函数(一):基本概念
python的函数(二):作用域
python的函数(三):参数传递
递归函数,简言之就是“自己调用自己”的函数。有点绕口,用一个简单的例子来说明。对一个列表求和,你会想到什么方法?
for循环,逐个加
内置sum()函数
上面的方法都不错。但今天我们用递归来对列表求和。
结果输出:
[1, 2, 3, 4, 5]
[2, 3, 4, 5]
[3, 4, 5]
[4, 5]
[5]
[]
15
这个例子中,把列表除第一个元素外的部分作为新列表,传递给递归函数。当列表为空时,就达到了递归结束的条件,计算出列表元素的和。这种方法仅仅用来演示递归函数的使用方法,大家在求和时还是要用前两种方法哈。
匿名函数,顾名思义就是没有名字的函数,临时的函数。下面举两个例子。
结果输出:
1 4 9 16 25 36
1 8 27 64 125 216
lambda是匿名函数的定义关键字,紧接着是参数x,冒号后面是函数主体,但函数主体只能写一句话。lambda语句执行后,创建了一个函数对象,但没有名字。上面这个例子里,我们把这些函数对象放在一个列表里。在使用时,用f指向这个对象,用f(x)形式来调用匿名函数。
通常匿名用inline形式,就是说作为一个表达式嵌入在代码里。再看一个例子。
结果输出:
点击按钮,终端里输出hello。
这个例子展示的是,在GUI编程时,可以用匿名函数实现一个简短的临时函数。比def要简洁很多。
我们已经知道函数是一个对象,由<class 'function'>定义。那么作为一个对象,也可以用自己的属性(成员变量)和方法(成员函数)。我们用dir()来研究一下函数内部是什么样的。
假定有一个函数
执行dir(func)显示如下:
['__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__']
dir()的返回值是一个函数对象内部属性和方法的列表。我们下面主要看看其中的__annotations__
, __code__
,__name__
等。
__name__里面保存的是函数的名字,print(func.__name__)
输出func。
__code__是函数的主体对象,并包括函数的参数等信息。我们执行print(dir(func.__code__))
输出如下:
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
例如,print(func.__code__.co_argcount)
输出函数的参数个数 2。print(func.__code__.co_varnames)
输出函数参数的列表 ('a', 'b')。
我们直接看下面的例子。
结果输出:
7
Error: a should be type int
None
这个例子,我们使用annotation来限制变量类型,当不符合变量类型时报错。其中:int指定变量类型。函数的返回值的annotation写在最后面-> int。
至此,函数部分讲完了,《Python在ASIC中的应用》的基础篇也结束了。各位童鞋学得怎么样?编程没有捷径,一定要多写,多思考!
下一次,我们一起学习《Python在ASIC中的应用》的中级篇,学习一些模块、文件读写、正则表达式等。