python学习之函数

python学习之函数

python的函数(或者说方法)与其它常用语言类似,都是面向过程的程序为了复用代码的产物,写法和PHP或者C++之类的语言一样随意,这多少和python的变量更像java那样一切均是对象有点向左,但不得不说不论风格,两者都显得相当的实用性格外突出。或许这就是之所以很多人推崇python适合作为入门学习的编程语言的原因吧。

一如之前,与其它语言类似的内容跳过,直接说一些独有或者需要注意的特性。

python的函数可以指定参数顺序

#指定参数顺序
def showPerson(name,age):
    print("name is "+name)
    print("age is "+str(age))
name="王二"
age=13
showPerson(age=age,name=name)

如上边的代码片段,python的函数可以无视定义时候的参数顺序,直接显示地指定传参对应的函数参数,这种特性在C++/PHP/JAVA中都是没有的,反而更像是一些IDE(比如android studio)的代码增强显示功能。至于这其中的必要性和优劣就不得而知了。

python的函数支持缺省参数

def showPerson(name,age=11):
    print("name is "+name)
    print("age is "+str(age))
name="王二"
age=13
showPerson(name)

如上边的代码,python的函数支持类似PHP中的做法

python的函数支持引用传参

def modifyList(list):
    list[0]="new"
    return
list=[1,2,3]
modifyList(list)
print(list)

运行结果为

['new', 2, 3]

如上边的代码所示,list作为引用传参,可以被函数修改内容,这和PHP/JAVA中类似。

函数的递归调用

def plusplus(n1,n2,list,maxTimes,curTimes):
    if curTimes>=maxTimes:
        return
    curTimes+=1
    n3=n1+n2;
    list.append(n3)
    plusplus(n2,n3,list,maxTimes,curTimes)
list=[1,1]
curTimes=3
maxTimes=10
plusplus(1,1,list,maxTimes,curTimes)
print(list)

同其它语言类似,并无二致。

友情提示:上边这个斐波那契数列递归运算的有点慢,一度以为有bug

简明教程这里看到一个递减,觉得颇为滑稽,递归应该作为一种层叠调用的思想,和终止条件无关

函数的函数以及nonlocal

def test1():
    a=1
    def test():
        nonlocal a
        a=2
    test()
    print(a)
test1();

运行结果为2

这是一个奇怪的特性,至少在C++/JAVA/PHP中都未曾遇见。在一个函数中可以嵌套定义函数,而内部函数可以通过nonlocal关键字访问父函数的变量,这有点像是JAVA中的内部类的用法。

把函数作为变量进行赋值

通过对python变量的学习,我们已经知道python中其实并没有常量变量之分,所有变量其实都是某种class的对象,而函数也是如此,所以就有了一些奇妙的用法,比如将函数作为变量赋值

def func ():
    print("this is a function")
func2=func
func()
func2()
print(id(func))
print(id(func2))
del func
#func()#会报错
func2()

执行结果

this is a function
this is a function
2791101334144
2791101334144
this is a function

从上边我们可以看到,python中函数不仅可以作为变量赋值,还可以使用del关键字删除,这就是解释型语言可以动态执行,和传统编译型语言的区别。具体传递过程同样是引用传递,func和func2通过引用传递指向同一个函数对象的地址,删除了其中一个(func),并不会触发拉级回收,因为func2的指向依然有效,可以正常调用。

将函数作为返回值

python中函数的返回值不仅可以是变量,也可以是函数

def test1():
    a=1
    def test():
        nonlocal a
        a=2
        print(a)
    return test
childFunc = test1()
childFunc();
print(type(test1))

运行结果为

2
<class 'function'>

可以看出python中的函数本身就是一种class对象,这点和javascript颇为相似,在js中函数就可以像对象一样进行操作。

将函数作为参数

和将函数作为返回值类似,函数也可以作为参数传递

def func(funcWillExe):
    print("here is func")
    funcWillExe()
def funcPrint():
    print("here is funcPrint")
func(funcPrint)

执行结果

here is func
here is funcPrint

匿名函数

python同样支持匿名函数,但写法颇为诡异,关键字也比较奇怪lambda

func1=lambda x,y: x+y
def func2(x,y):
    return x+y
print(func1(1,2))
print(func2(1,2))

运行结果为

3

3

从上边代码可以看出,2种函数声明可以等效,但相对于javascript或者java中的匿名函数,python的匿名函数颇为简陋,如果匿名函数要实现复杂逻辑不知道要如何编写程序。

装饰器

装饰器作为一种设计模式,在日常工作中使用广泛,比如对某种工作流,加入前处理和后处理事件。

def workflowBefore():
    print("this will do something before workflow")
def workflowAfter():
    print("this will do something after workflow")
def workflowDecorator(workflow):
    def decorator():
        workflowBefore()
        workflow()
        workflowAfter()
    return decorator
def workflow1():
    print("this is workflow1 execute")
def workflow2():
    print("this is workflow2 execute")
workflow1 = workflowDecorator(workflow1)
workflow2 = workflowDecorator(workflow2)
workflow1()
workflow2()

运行结果

this will do something before workflow
this is workflow1 execute
this will do something after workflow
this will do something before workflow
this is workflow2 execute
this will do something after workflow

因为python中函数具有对象的特性,所以实现修饰器模式还是相当便利的,如上边的示例,可以轻松构建一个用于修饰包装工作流的修饰器函数,只要传入不同的工作流,都可以统一修饰。但python还提供了一种更为简洁的写法。

def workflowBefore():
    print("this will do something before workflow")
def workflowAfter():
    print("this will do something after workflow")
def workflowDecorator(workflow):
    def decorator():
        workflowBefore()
        workflow()
        workflowAfter()
    return decorator
@workflowDecorator
def workflow1():
    print("this is workflow1 execute")
@workflowDecorator
def workflow2():
    print("this is workflow2 execute")
workflow1()
workflow2()

执行结果

this will do something before workflow
this is workflow1 execute
this will do something after workflow
this will do something before workflow
this is workflow2 execute
this will do something after workflow

可以看出两者区别,后者在定义将要被修饰的函数前使用@符号指定修饰器,定义后的函数就可以直接调用,不需要再进行修饰器的赋值操作。

关于修饰器的更多介绍可以阅读这里

生成器

简明教程里把生成器放在函数章节,而且内容颇为简单,个人觉得并不合适,所以在这里不过多讨论。

关于生成器的更多介绍可以阅读这里

参考资料

https://www.jmjc.tech/tutorial/python/21

本篇文章首发自魔芋红茶的博客https://www.cnblogs.com/Moon-Face/ 请尊重其他人的劳动成功,转载请注明。
原文地址:https://www.cnblogs.com/Moon-Face/p/14453090.html