python 函数篇 —— 作用域、参数类型、装饰器、高阶函数

python 函数篇 —— 作用域、参数类型、装饰器、高阶函数,第1张

概述文章目录函数变量和作用域函数的参数解压可迭代对象赋值给多个变量装饰器所需掌握的函数lambdamapreducefiltersortedenumeratezip函数变量和作用域使用函数的两个小习惯:当要定义的函数比较复杂时,可以对函数的参数和返回值进行注释,注释内容可以是任何形式(参数的类

文章目录函数变量和作用域函数的参数解压可迭代对象赋值给多个变量装饰器所需掌握的函数lambdamapreducefiltersortedenumeratezip

函数变量和作用域

使用函数的两个小习惯:

当要定义的函数比较复杂时,可以对函数的参数和返回值进行注释,注释内容可以是任何形式(参数的类型、作用、取值范围等),如下面代码中的(n:int)和( ->List),当然注释只是方便阅读代码,对程序的执行没有影响;函数体中使用文档声明,描述函数的相关信息;
def fib(n:int)->List:    """返回一个包含斐波那契数列的列表"""    result = []    a, b = 0, 1    while a < n:        result.append(a)        a, b = b, a+b    return result# 使用 fib.__annotations__ 可以查看注释

关于变量和作用域:

# enCoding: utf-8a = 1               # 全局作用域的变量 adef fn():    a = 2           # 嵌套作用域的变量 a    def inner_fn():        a = 3       # 当前作用域的变量 a# 上述代码只是方便叙述知识点

搜索变量的顺序是由内到外:

当前作用域变量 -> 嵌套作用域变量 -> 全局变量 -> python内置变量

global 和 nonlocal 关键字的区别:

在当前作用域下想 *** 作嵌套作用域的变量,使用 nonlocal;在当前作用域下想 *** 作全局变量,使用 global。
# enCoding: utf-8a = 1               # 全局作用域的变量 adef fn():    a = 2           # 嵌套作用域的变量 a    print('嵌套作用域变量a=', a)    def inner_fn():        nonlocal a      # global a        a = 3       # 当前作用域的变量 a    inner_fn()      # 这条语句若放在 inner_fn() 定义之前,会报错    print('嵌套作用域变量a=', a)print('全局变量a=', a)fn()print('全局变量a=', a)
函数的参数

参数的形态有:位置参数、默认参数、可变参数、关键字参数、命名关键字参数。

可变参数(*arg):传入的参数个数可以是 0个到任意个;可变参数在函数调用时自动组装为一个tuple;

def fn(name, *phone_numbers):    print('name:{}  phtoe_numbers:{}'.format(name,phone_numbers))fn('Stack')# name:Stack  phtoe_numbers:()fn('Thor', 110, 119, 120)# name:Thor  phtoe_numbers:(110, 119, 120)

关键字参数(**kw):允许传入 0个到任意个 带参数名的参数;关键字参数在函数内部自动组装为一个dict;

def fn(name, **kw):    print('name:{}  orther:{}'.format(name, kw))fn('Stack')name:Stack  orther:{}fn('Thor', job='thunder god', age=1500)name:Thor  orther:{'job': 'thunder god', 'age': 1500}

命名关键字参数(args,*,args):用来限制关键字参数的参数名;

'''注意查看 TypeError'''def fn(name, *, job, sex):    print('name:{}  orther:{}'.format(name, kw))fn('Stack')# TypeError: fn() missing 2 required keyword-only arguments: 'job' and 'sex'fn('Thor', job='thunder god', age=1500)# TypeError: fn() got an unexpected keyword argument 'age'

组合参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

解压可迭代对象赋值给多个变量使用 * 运算符从列表或元组中解包参数:
arr = [1, 2, 3, 4, 5]a, *b, c = arrprint('a={}, b={}, c={}'.format(a,b,c))# a=1, b=[2, 3, 4], c=5*a, b, c = arrprint('a={}, b={}, c={}'.format(a,b,c))# a=[1, 2, 3], b=4, c=5

这种解压语法通常用在具有特殊元素结构的可迭代对象上,如:

person = ['Tony Stack', 'Male', '[email protected]','[email protected]','[email protected]']name, sex, *email = personprint('email = ', email)# email =  ['[email protected]', '[email protected]', '[email protected]']
装饰器

装饰器就是用于拓展函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。

一个通俗的例子:

def working_hours(hours):    '''打印工作时长'''    print("Today's working_hours : ", hours)

现在要求在不改动函数代码的情况下增加新的功能:根据工时判断加班还是下班;

def working_overtime(func):    def wrapper(hours):        func(hours)     # 这条语句执行原函数功能,下面的条件语句是新增功能        if int(hours) < 8:            print('You have to keep working')        else:            print('Off work')    return wrapper      # working_Overtime函数的返回值必须是一个函数@working_overtime       # 相当于执行了 working_hours = working_overtime(working_hors)def working_hours(hours):    print("Today's working_hours : ", hours)working_hours(7)working_hours(9)# 输出结果Today's working_hours :  7You have to keep workingToday's working_hours :  9Off work

通过@working_overtime这条语句为原函数添加了一个装饰器,它相当于执行了 working_hours = working_overtime(working_hors)

以内层函数wrapper为标志,它内部的代码是核心区,是为原函数working_hours添加的新功能,原函数所需的参数可以同通过wrapper函数传递,wrapper函数可以没有返回值;

外层函数working_overtime相当于是传递原函数的接口,它和内层函数wrapper之间的部分可以有其它代码,不过这些代码不会被装饰到原函数上的,而是在装载装饰器时的附加 *** 作。

注意装饰器的返回值一定是一个函数。

def working_overtime(func):    print('此区域没有被装饰到原函数,无论原函数运行多少次,它只运行一次')    def wrapper(hours):        ...省略...    return wrapper@working_overtimedef working_hours(hours):    print("Today's working_hours : ", hours)working_hours(7)working_hours(9)# 输出结果此区域没有被装饰到原函数,无论原函数运行多少次,它只运行一次Today's working_hours :  7You have to keep workingToday's working_hours :  9Off work

当原函数参数较多时,装饰器可以使用*args, **kw的参数形式:

def deco(func):    ...    def wrapper(*args, **kw):        ...    returen wrapper    @decodef myfunc(*args, **kw):    ...

还有一种带参数的装饰器:

def daily_salary(hourly_salary):    '''新增计算日薪的功能'''    def working_overtime(func):        def wrapper(hours):            func(hours)            print('salary = ',hourly_salary * hours)        return wrapper    return working_overtime@daily_salary(40)def working_hours(hours):    print("Today's working_hours : ", hours)working_hours(7)working_hours(9)# 输出结果Today's working_hours :  7salary =  280Today's working_hours :  9salary =  360

值得一提的是,当某个函数有多个装饰器时,执行的顺序是:从下面的装饰器开始往上依次执行,最后执行原函数本身。

所需掌握的函数

Python 内置函数大全

lambda

使用 lambda 关键字可以创建一个匿名函数(通俗地说就是没有名字的函数),lambda函数可以在需要函数对象的任何地方使用。

语法形式:

 lambda argument_List: Expression

arhument_List 是参数列表,可以有多种形式;Expression 是关于参数的表达式,表达式只能是单行的。

lambda 函数最常用的用法是将其作为参数传递给其它函数。

map
map(func, *iterables) --> map object    """    Make an iterator that computes the function using arguments from    each of the iterables.  Stops when the shortest iterable is exhausted.    """

参数 func 是一个函数(func可以拥有多个参数),参数 iterable 是可迭代对象(iterable的个数对应func参数的个数);

map 函数将传入的函数依次作用到 iterables 的每个元素,并把结果作为新的 Iterator 返回。

# func 只有一个参数时,iterable 也只有一个map(lambda x : x*x, [1,2,3,4,5]# [1, 4, 9, 16, 25]# func 拥有多个参数时,iterable 拥有对应的个数map(lambda x, y, z: x+y+z, [1,2],(3,4,5),[6,7,8,9])# [10, 13]
reduce
reduce(function, sequence, initial=_initial_missing):    """    reduce(function, sequence[, initial]) -> value    Apply a function of two arguments cumulatively to the items of a sequence,    from left to right, so as to reduce the sequence to a single value.    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates    ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items    of the sequence in the calculation, and serves as a default when the    sequence is empty.    """# 源代码中有下面两条有语句,要求 function 有两个参数    for element in it:        value = function(value, element)

参数 function 是带有两个参数的函数 ,sequence 是可迭代对象;

reduce 函数将 function 从左至右累加的应用到 iterable 中的每个元素,最终返回一个累加值。

from functools import reduceprint(reduce(lambda x, y : 10*x + y, [1,2,3,0,6]))# 12306
filter
filter(function or None, iterable) --> filter object    """    Return an iterator yIElding those items of iterable for which function(item)    is true. If function is None, return the items that are true.    """

filter 函数把传入的函数依次作用于每个元素,根据返回值是 True 还是 False 决定保留还是丢弃该元素。

# function 是 None 时,iterable 会筛选一遍非空元素filter(None, [666, 'a', '', -1, 'False', False, [],[0,'b',False]])# [666, 'a', -1, 'False', [0, 'b', False]]# 筛选10以内的偶数filter(lambda x : x%2 == 0, range(11))# [0, 2, 4, 6, 8, 10]
sorted
sorted(iterable, *, key=None, reverse=False)

sorted 函数会将 iterable 里的元素进行排序;有两个可选参数 key 和 reverse,参数 key 指定一个函数(相当于排序依据),reverse 指定正序或逆序。

sorted([3, -5, 7, 0])# [-5, 0, 3, 7]sorted([3, -5, 7, 0], key=abs, reverse=True)# [7, -5, 3, 0]
enumerate
enumerate(iterable, start=0)     """    The enumerate object yIElds pairs containing a count (from start, which    defaults to zero) and a value yIElded by the iterable argument.        enumerate is useful for obtaining an indexed List:        (0, seq[0]), (1, seq[1]), (2, seq[2]), ...    """

enumerate 函数返回一个枚举对象,它的作用就是给 iterable 对象中的元素添加一个计数值,默认从o开始计数(若没有指定start)。

seasons = ['Spring', 'Summer', 'Fall', 'Winter']print(List(enumerate(seasons)))# [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]

enumerate 函数等价于:

def enumerate(sequence, start=0):    n = start    for elem in sequence:        yIEld n, elem        n += 1
zip
zip(*iterables)    """    return a zip object yIElding tuples until an input is exhausted.       >>> List(zip('abcdefg', range(3), range(4)))       [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)]    """

返回一个元组的迭代器,其中的第 i 个元组包含来自每个参数序列或可迭代对象的第 i 个元素。 当所输入可迭代对象中最短的一个被耗尽时,迭代器将停止迭代。 当只有一个可迭代对象参数时,它将返回一个单元组的迭代器。 不带参数时,它将返回一个空迭代器。

总结

以上是内存溢出为你收集整理的python 函数篇 —— 作用域、参数类型、装饰器、高阶函数全部内容,希望文章能够帮你解决python 函数篇 —— 作用域、参数类型、装饰器、高阶函数所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1186055.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存