九、递归函数、匿名函数、日期时间函数、随机函数、闭包、装饰器

一、递归函数

  • 定义:如果一个函数在内部,不调用其他的函数,而是调用自身的话,这个函数就是递归函数。
    程序实例如下所示:
def func(count):
    if count == 1:
        result = 1
    else:
        result = func(count-1)*count
    return result
number = int(input('请输入一个正整数:'))
print(func(number))
  • 执行原理如下
    九、递归函数、匿名函数、日期时间函数、随机函数、闭包、装饰器_第1张图片

二、匿名函数

  • 含义:没有名称的函数,如需声明匿名函数需要,使用关键字lambda
  • 语法:lambda [arg1 [,arg2,…argn]]:expression
  • [ arg 1 [,arg2,… .ar gn]]" 表示的是函数的参数。
  • expression" 表示的是函数的表达式。
  • 注意:
    (1)Lambda函数能接收任何数量的参数但只能返回一个表达式的值
    (2)匿名函数不能直接调用print,因为lambda需要一个表达式
  • 应用场合:函数作为参数传递

(1)自己定义的函数

>>> def fun(a, b, opt):
...     print("a = " % a)
...     print("b = " % b)
...     print("result =" % opt(a, b))
...
>>> fun(1, 2, lambda x,y:x+y)
a = 1
b = 2
result = 3

(2)作为内置函数的参数

  • 语法:列表.sort(key=lambda 临时变量名:临时变量名[key])
  • 默认是升序,使用reverse=True改为降序。
stus = [
    {"name": "zhangsan", "age": 18},
    {"name": "lisi", "age": 19},
    {"name": "wangwu", "age": 17}
]

stus.sort(key=lambda dict:dict["age"], reverse=True)
print(stus)

stus.sort(key=lambda d:d["name"])
print(stus)

# 列表嵌套
new_list = [[-100, 30, 10], [29, 31, 5], [10, 20, 6]]
# 想利用列表的小列表中的第三个元素进行排序
# [[29, 31, 5], [10, 20, 6], [-100, 30, 10]]
new_list.sort(key=lambda l:l[2])
print(new_list)

def 定义的函数和lambda 定义的函数的不同的地方:

  • def 定义的函数是有名称的,而 lambda 定义的函数没有函数名称,这是最明显的区 别之一。
  • lambda 定义的函数通常会返回一个对象或者一个表达式,它不会将返回结采赋给一个 变量,而 def定义的函数则可以。
  • lambda 定义的函数中只有一个表达式,函数体比 def定义的函数简单很多,而 def定义 的函数的函数体是一个语句。
  • lambda 表达式的冒号后面只能有一个表达式, def 定义的函数则可以有多个。
  • 像 if或 for 等语句不能用于 lambda 定义的函数中,而 def定义的函数则可以使用。
  • lambda 一般用来定义简单的函数,而 def可以定义复杂的函数。
  • == lambda 定义的函数不能共享给别的程序调用==,而 def 定义的函数则可以被调用 。

三、日期时间函数

3.1 时间函数

在 Python 中,通常有如下几种方式表示时间:

  • 时间戳 ;
  • 格式化的时间字符串
  • 时间元组( struct_time )

3.1.1 时间戳

  时间戳表示的是从 1970 年 1 月 1 日 00:00:00 开始按秒计算的偏移量。返回时间戳的函数主要有 time()、 clock()等

import time
a = time.time()
print("当前时间戳为:", a)
#-------
#当前时间戳为: 1546056474.8554897

3.1.2 格式化的时间字符串

import time

# 格式化为 2018-12-29 12:18:18
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))

# 格式化为 Sat Dec 29 12:18:18 2018
print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()))

# 将格式字符串转换为时间戳
time_word = 'Sat Mar 28 22:24:24 2018'
print(time.mktime(time.strptime(time_word, "%a %b %d %H:%M:%S %Y")))

python中时间日期格式化符号:

符号 含义
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身

3.1.3 时间元组

  返回 struct_time 的函数主要有 gmtime()、 localtime()和 strptime(), struct_time 元组共有九 个元素,我们通过一张表来列出元组中的这些元素。

字段
tm_year 2008
tm_mon 1 到 12
tm_mday 1 到 31
tm_hour 0 到 23
tm_min 0 到 59
tm_sec 0 到 61 (60或61 是闰秒)
tm_wday 0到6 (0是周一)
tm_yday 一年中的第几天,1 到 366
tm_isdst 是否为夏令时,值有:1(夏令时)、0(不是夏令时)、-1(未知),默认 -1
#!/usr/bin/python3
import time

localtime = time.localtime(time.time())
print ("本地时间为 :", localtime)

以上实例输出结果:

本地时间为 : time.struct_time(tm_year=2016, tm_mon=4, tm_mday=7, tm_hour=10, tm_min=28, tm_sec=49, tm_wday=3, tm_yday=98, tm_isdst=0)

3.1.4 time模块的函数

  星期一是默认的每周第一天,星期天是默认的最后一天。更改设置需调用calendar.setfirstweekday()函数。模块包含了以下内置函数:

calendar.calendar(year,w=2,l=1,c=6)

返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为21* W+18+2* C。l是每星期行数。

calendar.firstweekday( )

返回当前每周起始日期的设置。默认情况下,首次载入caendar模块时返回0,即星期一。

calendar.isleap(year)

是闰年返回 True,否则为 false。

calendar.leapdays(y1,y2)

返回在Y1,Y2两年之间的闰年总数。

calendar.month(year,month,w=2,l=1)

返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。

calendar.monthcalendar(year,month)

返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。

calendar.monthrange(year,month)

返回两个整数。第一个是该月的星期几,第二个是该月有几天。星期几是从0(星期一)到 6(星期日)。

>>> import calendar
>>> calendar.monthrange(2014, 11)
(5, 30)

(5, 30)解释:5 表示 2014 年 11 月份的第一天是周六,30 表示 2014 年 11 月份总共有 30 天。

calendar.prcal(year,w=2,l=1,c=6)

相当于 print calendar.calendar(year,w,l,c).

calendar.prmonth(year,month,w=2,l=1)

相当于 print calendar.calendar(year,w,l,c)。

calendar.setfirstweekday(weekday)

设置每周的起始日期码。0(星期一)到6(星期日)。

calendar.timegm(tupletime)

和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间戳(1970纪元后经过的浮点秒数)。

calendar.weekday(year,month,day)

返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。

四、随机函数

random.random()

返回 0与1之间的随机浮点数 N ,范围为 0<= N < 1 .0。

random.uniform(a,b)

返回 a 与 b 之间的随机浮点数 N ,范围为[a, b]。 如果 a 的值小于 b 的值,贝IJ生成的随机浮 点数 N 的取值范围为 a <= N <= b; 如果 a 的值大于 b 的值,则生成的随机浮点数 N 的取值范 围为 b <= N <= a。

random.randint(a,b) 

返回一个随机的整数 N , N 的取值范围为 a <= N <= b。需要注意的是, a 和 b 的取值必须 为整数,并且 a 的值一定要小于 b 的值。

 random.randrange([start], stop[, step]) 

返回指定递增基数集合中的一个随机数,基数默认值为 1。其中, start 参数用于指定范围内的开 始值,其包含在范围内; end 参数用于指定范围内的结束值,其不包含在范围内; step 表示递增基数。 上述这些参数必须为整数。例如 , random.randrange (10, 100, 2)相当于从[10, 12, 14, 16, … 96, 98]序列中获取一个随机数。

 random.choice(sequence) 

从 sequence 中返回一个随机的元素。其中, sequence 参数可以是列表、元组或字符串。 需要注意的是,若 sequence 为空,则会引发 IndexError 异常。

 random.shuffle (x[,random]) 

用于将列表中的元素打乱l顺序,俗称为洗牌

random.sample(sequence,k)

从指定序列中随机获取 k 个元素作为一个片段返回, sample 函数不会修改原有序列。

五、闭包

闭包需要满足如下三个条件:

  • 存在于嵌套关系的函数中。
  • 嵌套的内部函数引用了外部函数的变量。
  • 嵌套的外部函数会将内部函数名作为返回值返回。
def outer(start=0):
    count = start

    # 内部函数
    def inner():
        nonlocal count
        count += 1 # 引用外部函数的变量
        return  count
    # 返回内部函数的名称
    return inner

quote = outer(5)
print(quote())
#--------结果---------
# 6

从变量的生命周期的角度来讲,在 outer 函数执行结束以后,变量 count 已经被销毁了。当 outer 函数执行完后,会再执行内部的 Inner 函数,由于 Inner 函数中使用了 count 变量,所以程 序应该出现运行时错误。然而,程序仍能正常运行,这是为什么呢?

究其原因,主要在于函数的 闭包会记得外层函数的作用域,在 Inner 函数(闭包)中引用了外部函数的 count 变量,所以程序是不会释放这个变量的。

六、装饰器

  • 装饰器的含义:装饰器本质是一个 Python 函数,它可以在不改动其他函数的前提下,对函数的功能进行扩 充。
  • 装饰器用于下列场景:
  • 引入曰志;
  • 函数执行时间统计;
  • 执行函数前预备处理;
  • 执行函数后清理功能;
  • 权限校验;
  • 缓存。
def wrap_one(func):
    print('正在装饰1')

    def inner():
        print('正在权限认证1')
        func()
    return inner


def wrap_two (func):
    print('正在装饰2')

    def inner():
        print('正在权限认证2')
        func()
    return inner


@wrap_one
@wrap_two
def test():
    print('--------test----------')

test()
# -------结果-----------
# 正在装饰2
# 正在装饰1
# 正在权限认证1
# 正在权限认证2
# --------test----------

多个装饰器可以应用在一个函数上,它们的调用顺序是自下而上的。

6.1 装饰器对有参数函数进行装饰

如果无法确定函数的参数个数以及参数类 型,我们可以使用不定长参数来传递,示例代码如下:

def wrap_one(func):
    print('正在装饰1')

    def inner(*args, **kwargs):
        print('正在权限认证1')
        func(*args, **kwargs)
    return inner


@wrap_one
def test(*args, **kwargs):
    print('--------test----------')
    a = args
    print(a)
    b = kwargs
    print(b)
test(1,2,3, a= 6)

6.2 装饰器对带有返回值的函数进行装饰

需要使用 return 语句将调用后的结果返回,示例代码如下:

def wrap_one(func):
    print('正在装饰1')

    def inner(*args, **kwargs):
        print('正在权限认证1')
        return func(*args, **kwargs)
    return inner


@wrap_one
def test(*args, **kwargs):
    print('--------test----------')
    a = args
    b = kwargs
    return a, b
result = test(1,2,3, a= 6)
print(result)

6.3 带有参数的装饰器(工厂函数)

如果我们给 装饰器添加参数,那么需要增加一层封装, 先传递参数,然后再传递函数名。 下面看一段代码

def wrap_args(*args, **kwargs):

    def wrap_one(func):
        print('正在装饰1')

        def inner():
            print('正在权限认证1')

            return func(*args, **kwargs)
        return inner
    return wrap_one


@wrap_args(1, 2, a=4)
def test(*args, **kwargs):
    print('--------test----------')
    a = args
    b = kwargs
    return a, b
result = test()
print(result)

七、python常见的内置函数

7.1 map函数

  • map 函数会根据提供的函数对指定的序列做映射。
map(function, iterable,...)

(1)第一个参数 function 表示的是一个函数名,第二个参数 iterable 可以是序列、 支持迭代的容器或迭代器。当调用 map 函数时, iterable 中的每个元素都会调用 function 函数, 所有元素调用 function 函数返回的结果会保存到一个迭代器对象中
(2)这里说明一下,在 Python 2 中, map 函数的返回值是到表 list 类型如果希望将迭代器对象转为列表,则可以通过 list 函数进行转换。 此外,还可以使用 for 循 环直接遍历迭代器对象,从而取出其内部的每个元素。
(3)在 Python3 以前,如果调用 map 函数时传入的 function 参数为 None,那么相当于合并参 数为元组。
(4)在 Python 3 以后,当 map 传入的函数为 None 时,就等同于 zip 函数(用于将可迭代的对 象作为参数, 将对象中对应的元素打包成一个个元组, 然后返回由这些元组组成的列表 ) 的功能, 并且已经被 zip 函数取代了。另外, map 函数无法处理两个序列长度不一致、对应位置操作数类 型不一致的情况,它们都会报类型错误

result = map(lambda x,y: x+y, [1,2,3], [4, 5, 6])
print(list(result))
#-----结果-------
# [5, 7, 9]

7.2 filter函数

  • filter 函数会对指定序列执行过滤操作。
filter(function, iterable,..)

(1)第一个参数 function 可以是函数名称或者 None ,第二个参数 iterable 可以 是序列、支持迭代的容器或迭代器。返回值为迭代器对象( Python2 中, map 函数的返回值是列 表类型)。其中,== function 函数只能接收一个参数, 而且该函数的返回值为布尔值==。
(2)filter 函数的作用是以参数迭代器中的每个元素分别调用 function 函数,最后返回的迭代器包含调用结果为 True 的元素。示例代码如下 :

result = filter(lambda x: x**2, [0,2,3])
print(list(result))
# --------结果----------------
# [2, 3]

7.3 reduce函数

  • reduce 函数会对参数迭代器中的元素进行累积。
functools.reduce(function, iterable[,initializer])

(1)function 是一个带有两个参数的函数;第 2 个参数 iterable 是一个迭代器对 象; initializer 表示固定的初始值。 reduce 函数会依次从迭代器对象中取出每个元素,和上一次 调用 function 的结果做为参数再次调用 function 函数。

import functools

function = lambda x,y : x+y
iterable = [1, 2, 3]
result = functools.reduce(function, iterable, 0)
print(result)
# ----------结果-------------
# 6

你可能感兴趣的:(python基础)