本文将按照如下结构介绍:




execute在python中的用法 python execute函数_python中line函数


1.函数介绍

1.1 函数的定义

函数其实有5部分组成,分别是定义函数的关键字,函数的名字,圆括号(存放函数的参数),函数功能的实现,函数的返回语句。

  • 函数的关键字,定义函数要使用关键字def开头,后面跟着函数的名字 。两者中间相隔一个空格。
  • 函数的名字,每个函数都要有一个名字即函数标识符,函数名字是由开发人员起的,起的名字最好有一定业务语义,比如此功能是一个加法的操作,那么就可以起add.
  • 圆括号,圆括号内可以定义参数,参数可以是一个,也可以是多个,也可以没有参数 。圆括号后必须要有个冒号并且加缩进,
  • 函数功能实现代码,冒号+缩进的后面就可以编写函数的功能代码块了,但这部分一般都是放在函数的下一行 。
  • 函数的返回语句,函数使用return代表函数已经结束,不带表达式return代表返回None 。

函数的语法格式:


def 函数名(参数列表):
    函数体
    return


示例:


#不带参数的函数
def hello_world():
    print("hello world")
#带一个参数
def show(msg)
    print(msg)
#带多个参数
def add(x,y):
    z = x + y
    return z


1.2函数的调用

调用函数,其实就是使用函数。调用函数时直接使用函数名即可。

调用语法:


函数名(参数列表)


调用以上定义的函数


#1.调用hello_world函数
hello_world()
#2.调用show函数
show("我是一个函数")      #输出:我是一个函数
#3.调用add函数
print(add(3,4))         #输出:7


1.3函数的返回

函数的返回用于退出该函数,函数返回使用return进行表示,return后面可以根具体值,也可以不跟。如果不跟任何值代表返回None。

一般return后的值有以下几种情况:

  • return None,如果是None,可以忽略不写 。
  • return value,value可以是代码块中计算出来的值,也可以是一个表达式 。
  • return val1,...,valn。return也可以返回多个值,注意:返回多个值时接收需用对应的多个变量。

示例


def show(msg):
    print(msg)
    return None             #这样代码可以忽略。

def add(x,y):
    z = x +y
    return z                #返回某个值

def add(x,y):
    return x + y            #直接返回参与运算后的结果

def calc(x,y):
    add = x+y
    sub = x-y
    return add,sub          #返回了两个值


1.4 小结

最后,我们将上面讲的内容通过一张思维导图来总结,具体如下


execute在python中的用法 python execute函数_python中line函数_02


2.函数的参数

在调用函数时,经常会用到形式参数(简称“形参”)和实际参数(简称“实参”),二者的主要区别是:

  • 形式参数,是在括号内的参数就叫形式参数,例如上面add函数:
def add(x,y):           #这里的x,y就是形式参数
    z = x + y
    return z


  • 实际参数,调用函数时,实际传入到函数内的值 。
print(add(3,4))         #调用add函数时,实际传入的3和4就是实际参数 。


需要注意的是,一个函数实际上可以接受任何类型的值,比如字符串,整数,浮点数,列表,元组,字典等。

当函数的形式参数中要传递实际的值时,也会分两种情况,不可变对象值(值传递)传递和可变对象值传递(引用传递)。

函数中的不可变对象值传递,示例:


x = 10
def sum(a):
    a += 2
    return a

print("调用函数后返回的值:",sum(x))
print("x的值:",x)


运行后可以看出,无论函数中如何作用x的值,实际的x值是不会发生变化的 ,传入sum函数里的值其实就是x=10的一份副本 。


execute在python中的用法 python execute函数_python中line函数_03


函数中的可变对象传递,示例


my_lst = ['java', 'c++', 'python','go']
def update_lst(lst):
    lst.insert(1,'ruby')
    return lst

print("调用函数后返回的值:",update_lst(my_lst))
print("my_lst的值:",my_lst)


运行结果:


execute在python中的用法 python execute函数_python中line函数_04


以上结果可以看出,通过函数作用于my_list列表后,列表内的值也发生改变了,他们两同时指向了一个列表 。

最后,用个形象的例子总结一下,不可变对象就像是一个pdf文件,文件内容本身不能改变,但是可以拷贝,所以在函数中使用不可变对象都是使用的是拷贝后的副本。而可变对象就像是execl。execl中的内容时可变化的 。但是操作的都是源文件,函数中操作的可变对象也是对源文件里的内容进行操作 。

从参数的类型划分,可以将参数划分为:位置参数,默认参数,关键字参数,可变参数。

2.1 位置参数:

所谓的位置参数,主要是指输入函数内的参数数量和位置要和定义的形参中的一致。传多或传少都会报错。


#实例:
def add(x,y):           #定义了两个形参,调用该方法时必须传入两个参数值,传多或传少都会报错
    z = x + y
    return z

#输出
print(1,2)      #位置参数传入正确
print('hello','world')  #位置参数传入正确
print(3)        #不正确,报TypeError异常
print(1,2,3)    #不正确,报TypeError异常


2.2 默认参数

如果函数的某个参数经常会使用到一个值,那我们就可以给这个参数设置一个默认值 ,当调用该函数时,该参数若不传入值,就会使用到默认值。设置的默认参数需放在关键字参数后 。

示例:


#默认参数实例
def show_lgg(msg,lgg='python'):
    info = ("{}{}".format(msg,lgg))
    return info

print(show_lgg("使用默认的开发语言:"))
print(show_lgg("使用默认的开发语言:",'java'))

#输出
使用默认的开发语言:python
使用默认的开发语言:java


从以上结果可以看出,函数show_lgg中的lgg设置了默认值python,当该参数没有传值时,使用的是默认的值。若该参数传入值后,使用的就是传入的值 。

那这个默认参数的用处就是,当函数的参数值频繁的使用某一个值或者优先被使用该值时,都可以将其设置为默认值 。比如我们经常使用的浏览器,那么多的浏览器中,我们最常用的Chrome,那么就可以将Chrome设置为默认值。不传入该参数时默认就会使用Chrome 。

使用默认参数时要注意,位置参数需放在默认参数前面,否则python会报错。使用它可以简化我们的调用,增加灵活度。

2.3 关键字参数

关键字参数是指传递给参数要以key=value形式,key代表函数中的形参名称,value就是传递给函数的实际的值。

使用关键字参数后,参数的位置就可以进行调换了 。


#关键字参数实例
def student_lesson(grade,subject):
    z = "{}年级上{}课".format(grade,subject)
    return z

print(student_lesson(3,'英语'))           #位置参数
print(student_lesson(grade=4,subject='数学'))     #关键字参数
print(student_lesson(subject='语文',grade=5))     #关键字参数可以调换位置
print(student_lesson(6,subject='体育'))           #关键字参数和位置参数混合使用。

#输出
3年级上英语课
4年级上数学课
5年级上语文课
6年级上体育课


以上方式都可以正常正常调用,但是需要注意的是,当关键字参数和位置参数混合使用时,位置参数必须在前,关键字参数在后,否则会报错。

2.4 可变参数

这里的可变化参数指的参数的数量可以发生变化,比如我可以传递3个参数,也可以传递6个,甚至更多 。可变化参数有两种类型,分别是用来接收元组或列表形式的可变参数;另外一种是用来接收字典形式的可变参数 。


#列表形式的语法格式:
def fun_name(a,b,*args):    
    pass

#代码实例
def show_info(*args):
    print(args)

show_info()                                 #可变参数也可以不传入任何参数
show_info("python")                         #传入一个参数
show_info("python",'java')                  #传入多个参数
show_info(*['python','java'])               #传入列表,注意,列表前需要加*
show_info(*('python','java'))               #传入元组,元组前也需要加*

#输出:
()
('python',)
('python', 'java')
('python', 'java')
('python', 'java')


在可变参数的参数名前需加*代,这样就代表该参数为可变参数了。同时也传入的时候可以是一个值,多个值,列表或元组 。

还有一种可变参数就是接收字典中的元素 。在函数中是以双星**表示。此函数同样能接收多个位置参数,但是传入的形式需要以关键字形式传递 。


#字典形式的可变参数语法格式
def fun_name(a,b,**kw): 
    pass

#代码实例
def show_info(**kwargs):
    print(kwargs)

show_info()                                 #可变参数也可以不传入任何参数
show_info(key1="python")                            #传入一个参数
show_info(key1="python",key2='java')                    #传入多个参数
show_info(**{'key1':'python','key2':'java'})                #传入列表,注意,列表前需要加*

#输出:
{}
{'key1': 'python'}
{'key1': 'python', 'key2': 'java'}
{'key1': 'python', 'key2': 'java'}


也可以将可变参数列表和字典形式结合起来使用 。


def fun_name(*args,**kwargs):       #此函数可以接收任何长度,任何位置,任何关键字的参数 。
    pass


针对以上四种参数,进行总体说明:

  • 位置参数,参数的顺序和个数固定,调用函数时也必须按照该顺序和个数进行传递 。但如果参数个数固定了,就不容易扩展了 。所以,可以使用可变参数传入不同数量的参数 。
  • 关键字参数,使用形参名称=输入的值来进行表示,如果使用关键字参数,就可以调换参数的位置 ,可变参数的字典形式其实就是关键字参数的扩展,可以支持不同长度的关键字参数。
  • 默认参数,是针对位置参数的,相当于给某一个或几个位置参数设置默认值。
  • 可变化参数,可以扩展位置参数的数量,支持列表形式和字典形式的位置参数 。

2.5 小结

最后,我们将上面讲的内容通过一张思维导图来总结,具体如下


execute在python中的用法 python execute函数_python中line函数_05


3.高级函数

3.1 匿名函数

使用关键字lambda的表达式,又称为匿名函数。若函数可以用一行进行实现的话,那么该函数就可以使用匿名函数来代替。


#格式:
    lambda x,y,...,n:表达式
#说明:x,y,...,n.相当于普通函数的位置函数,可以是一个,也可以是多个 。
#实例:求两个数的和
    #实现1:普通实现
    def add(a,b):
        return a + b
    
    z1 = add(3,4)
    print(z1)           #输出:7
    
    #实现2:通过匿名函数
    z2 = lambda x,y:x+y
    print(z2)           #<function <lambda> at 0x0326C618>
    print(z2(4,5))      #输出:9


匿名函数除了可以赋值给变量外,还可以通过函数的参数来传递参数。


#实现:将函数的参数a,b传递给匿名函数
def add(a,b):
    z = lambda :a+b
    return z


3.2 高阶函数-map,reduce,filter,sorted

map函数

map()是python的内置函数。map()函数接收两个或多个参数,第一个参数接收的是函数,后面的参数是序列。


#语法:
    map(函数,序列)
        
#实例:将列表中的每一对元素相加
lst = [(1,2),(3,4),(4,5)]
total = map(sum,lst)
print(list(total))

#输出:
[3, 7, 9]

#说明:
    以上代码相当于把(1,2),(3,4),(4,5)这三组中的每两个元素传递给sum,然后由sum来进行运算 。


map后面的序列也可以是多个


#语法:
    map(函数,序列1,序列2,...)
    
#实例
num = map(lambda x,y:x+y,[1,2,3,4,5],[6,7,8,9,10])
print(list(num))

#输出:
[7, 9, 11, 13, 15]

#说明:
    map的第二个,第三个参数都是列表,结果就是将这两个列表每一个位置的数进行相加


reduce函数

接收两个参数,第一个是函数,第二个是序列 。reduce()函数会把序列中的每一个元素累积进行计算,如何计算由前面的函数来定。


#语法:
    reduce(函数,序列)
    
#实例:把列表中的数进行相加
from functools import reduce

def add(x,y):
    return x + y

sum = reduce(add,[1,2,3,4,5])
print(sum)

#输出:15

#说明:相当于是把整个列表的数进行了一次循环的相加操作


filter函数

也是接收两个参数,第一个是函数,第二个是序列,filter()函数会把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。


#语法:
    filter(函数,序列)
    
#实例:查询字典中成绩分大于350分的元素

dt = {'grade_one': 237, 'grade_two': 532, 'grade_three': 356}
dt1 = dict(filter(lambda x:x[1] > 350,dt.items()))
print("查询年级分数大于350分的班级:{}".format(dt1))

#输出:
查询年级分数大于350分的班级:{'grade_two': 532, 'grade_three': 356}


sorted函数

sorted函数对所有可迭代的对象进行排序


#语法
    sorted(iterable, cmp=None, key=None, reverse=False)     ==等价于下面的
    sorted(可迭代对象,比较函数,用来比较的元素,排序规则)
    
#实例:
    study = [('ruby', '3本', 150), ('python', '21本', 122), ('java', '18本', 210)]
    print("按第三个元素(价格)排序:{}".format(sorted(study, key=lambda s: s[2])))
    print("按第二个元素(书籍)降序排序:{}".format(sorted(study, key=lambda s:s[2],reverse=True)))
    
#输出:
    按第三个元素(价格)排序:[('python', '21本', 122), ('ruby', '3本', 150), ('java', '18本', 210)]
    按第二个元素(书籍)降序排序:[('java', '18本', 210), ('ruby', '3本', 150), ('python', '21本', 122)]


3.3 偏函数

偏函数其实就是functools包中的partial函数。

在前面我们讲到函数的默认值可以减少传递参数的数量,但是一旦定义了函数的默认值,如果修改的话,就得修改这个函数,很多情况我们底层的一些函数都是不建议修改的,这个时候可以使用偏函数来设置默认值,而且不同的类型可以设置不同的默认值 。


#简化版计算器
def calc(x,y,op='+'):
    if op == '+':
        return x + y
    if op == '-':
        return x - y
    if op == '*':
        return x * y
    if op == "/":
        return x / y
    return x + y

#需求:这时我们又需要进行大量的乘法操作,怎么办呢? 如下面的操作
calc(2,3,"*")
calc(2,4,"*")
calc(2,5,"*")
...
calc(2,n,"*")

#注意:这个时候不建议修改原函数,因为原函数也是综合考虑使用+最多的。不能这时用*就修改原函数为* 。
#问题:每次传入的第三个值都是一个值,比较麻烦。能否把它作为默认参数传进来,
#解决方案:使用偏函数
from functools import partial

mult=partial(calc,op='*')       #把乘法固定
print(mult(2,4))    #输出:8
print(mult(6,4))    #输出:24

#说明,使用偏函数后,参数op的默认值已经给定,所以后面不需要再传递该参数 。


3.4 递归

递归就是函数内部又调用了自己的函数就被称为递归 。


#语法格式
def funA(
    ...
    funA()
    ...
)

#实例1:求:1!+2!+3!+4!+5!+...+n!

def factorial(n):
    ''' n表示阶乘数的最大值 '''
    if n==1:
        return n # 阶乘为1的时候,结果为1,返回结果并退出
    n = n*factorial(n-1) # n! = n*(n-1)!
    return n  

res = factorial(5) 
print(res) 

#输出:120
#===============================

#实例2: 1,1,2,3,5,8,13,21,34,55,试判断数列第23个数是哪个?
def fab(n):
    ''' n为斐波那契数列 '''
    if n <= 2:
        ''' 数列前两个数都是1 '''
        val = 1
        return val 
    val = fab(n-1)+fab(n-2) # 由数据的规律可知,第三个数的结果都是前两个数之和,所以进行递归叠加
    return val
print(fab(23))

#输出:28657


3.5 闭包和装饰器

闭包

闭包又称为闭合函数。简单来说,闭包的概念就是在函数内再定义一个函数,这个内部函数使用了外部函数的临时变量,且外部函数的返回值是内部函数的引用时,我们称之为闭包。


语法:
    def outer_func():       #外部函数
        temp = null         #外部函数的临时变量
        def inner_func():
            函数体
        return inner_func       #将内部函数作为返回值返回
    
#实例
import operator

def operating(op):      #外部函数定义具体的操作符
    def calc(a,b):          #内部函数定义计算的两个变量
        oprt = {
            '+': operator.add(a,b),
            '-': operator.sub(a,b),
            '*': operator.mul(a,b),
            '/': operator.truediv(a,b)
        }
        return oprt.get(op)
    return calc             #把内函数的引用当做外函数的变量值返回

add = operating('+')
print(add(3,4))     #输出:7


那么,闭包最主要的用途就是装饰器 。

装饰器

装饰器的本质其实就是一个闭包函数,以下就是一个最为普通的装饰器,


def info(func):
    def wrapper():
        print("[INFO]: 调用 {}()".format(func.__name__))
        return func()
    return wrapper

def say():
    print("hello!")

say_hello = info(say)  # 添加功能并保持原函数名不变


通过和闭包进行相比较,两者的写法都是一样的,其实装饰器就是一个闭包函数 。那么除了以上调用方法外,python在后续的版本又引入了@语法糖,同样是上面的代码,可以使用如下方式调用 。


def info(func):
    def wrapper():
        print("[INFO]: 调用 {}()".format(func.__name__))
        return func()
    return wrapper

@info
def say():
    print("hello!")
    
say()

#输出:
[INFO]: 调用 say()
hello!


这样的话,就通过@ 标识符将装饰器应用到函数上了 。其实通过以上的调用,实际上是执行了如下2步操作:

  1. 将say传给info()函数 。
  2. 将info函数执行完成的返回值反馈say

以上是一个最简单的装饰器,但有一个问题,如果被装饰的函数需要传入参数,那么这个装饰器就不能用了 ,因为返回的函数并不能接受参数 。

带参数的函数装饰器

通过制定装饰器函数wrapper接受和原函数一样的参数,就可以参数了 。


def info(func):
    def wrapper(arc):  #
        print("[INFO]: 调用 {}()".format(func.__name__))
        return func(arc)
    return wrapper  # 返回包装过函数

@info
def say(arc):
    print("hello {}.".format(arc))
    
say("装饰器函数")
    
#输出
[INFO]: 调用 say()
hello 装饰器函数.


以上还是只能接受一个参数,但实际情况下,同一个装饰器可用于多个不同的函数,每个函数所带的参数都各不相同,怎么解决呢 ?

这时我们就可以用到可变参数*args和**kwargs了。通过这两个参数,装饰器就可以用于任意函数了 。


def info(func):
    def wrapper(*args, **kwargs):  # 指定*args和**kwargs,接收任意参数
        print("[INFO]: 调用 {}()".format(func.__name__))
        return func(*args, **kwargs)
    return wrapper  # 返回

@info
def say(arc1):
    print("hello {}!".format(arc1))

@info
def todo(x,y):
    print(x * y)


say("作用于多个函数的装饰器")
todo(3,5)

#输出:
[INFO]: 调用 say()
hello 作用于多个函数的装饰器!
[INFO]: 调用 todo()
15


3.6 回调函数

简单的来说,把一个函数作为参数传给另一个函数,那么这个函数就是回调函数。这个被传入的参数其实是函数指针,即指向一个函数的指针(地址)。


def calc(func,a,b):     #第一个参数接收一个函数
    return func(a,b)


def add(x,y):
    return x + y

def mul(x,y):
    return x * y

print(calc(add,3,5))        #第一个参数为函数,后面的两个参数是函数的参数
print(calc(mul,3,5))        

#输出
8
15


回调函数还可以进行异步调用,即非阻塞调用,通常用在多线程或者多进程中。

3.7 生成器函数

生成器函数,就是说定义函数时,内部带yield就算生成器函数。在调用生成器运行的过程中,每次遇到 yield 就会返回 其后的值, 并在下一次执行 next() 方法时从当前位置继续运行。


def scq_func():
    for x in range(1,10):
        yield x * 2

s = scq_func()
print(s)       #输出:<generator object scq_func at 0x0161B510>
print(next(s))
print(next(s))
print(next(s))
print(next(s))

#输出:
<generator object scq_func at 0x0161B510>
2
4
6
8


以上函数在执行过程中,遇到yield就中断下次又继续执行,直到没有yield可执行了,在调用next就会报错 。

那该函数主要的作用是什么呢 ? 在数学中有很多的计算都是无限穷尽的(比如自然数) 。我们不可能通过序列去存放,这时我们就可以使用生成器按照规则计算下出一个数据,可以计算出很大的数 。


import sys
 
def fibonacci(n): # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
 
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()
        
#输出:
0 1 1 2 3 5 8 13 21 34 55


3.8 小结

最后,我们将上面讲的内容通过一张思维导图来总结,具体如下


execute在python中的用法 python execute函数_python中line函数_06