前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python从0到100(十四):高级函数及函数使用进阶

Python从0到100(十四):高级函数及函数使用进阶

原创
作者头像
是Dream呀
发布2024-04-23 11:25:22
780
发布2024-04-23 11:25:22
举报
文章被收录于专栏:总结xyp总结xyp

一、高级函数

1.时间函数

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

(1)时间戳;

(2)格式化的时间字符串;

(3)时间元组(struct_time)。

1.通常来讲,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。

代码语言:python
复制
import time;  # 引入time模块
ticks = time.time()
print("当前时间戳为:", ticks)

2.我们可以使用time模块的strftime方法来格式化日期

代码语言:python
复制
import time
# 格式化成2016-03-20 11:45:39形式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.返回struct_time的函数主要有gmtime()、localtime()和strptime(),struct_time元组。

2.日历函数

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

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

代码语言:python
复制
import calendar
print(calendar. firstweekday())
print(calendar.isleap(2018))
print(calendar.calendar(2021,w=1,l=1,c=6))

然后就可以得到我们的日期表了,是不是非常的nice:

在这里插入图片描述
在这里插入图片描述

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

代码语言:python
复制
calendar. firstweekday()

3. 如果是闰年返回True,否则为false。

代码语言:python
复制
calendar.isleap(year)

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

代码语言:python
复制
calendar.leapdays(y1,y2)

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

代码语言:python
复制
print(calendar.month(2021,2,w=2,l=1))
在这里插入图片描述
在这里插入图片描述

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

代码语言:python
复制
calendar.monthcalendar(year,month)
在这里插入图片描述
在这里插入图片描述

7. 返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码。日从0(星期一)到6(星期日);月从1到12。

代码语言:python
复制
calendar.monthrange(year,month)

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

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

3.随机数函数

1.random.random()

用于生成一个0到1的随机符点数: 0 <= n < 1.0。

代码语言:python
复制
import random# 生成第一个随机数
print("random():", random.random())# 生成第二个随机数 
print("random():", random.random())

2.random.uniform(a,b)

返回a,b之间的随机浮点数,范围[a,b]或[a,b]取决 于四舍五入,a不一定要比b小。

3.random.randint(a,b)

返回a,b之间的整数,范围[a,b],注意:传入参数必须是整数,a一定要比b小。

4.random.randrang([start], stop[, step])

返回有个区间内的整数,可以设置step。只能传入整数,random.randrange(10, 100, 2),

结果相当于从[10, 12, 14, 16, … 96, 98]序列中获取一个随机数。

5.random.choice(sequence)

从sequence(序列,是有序类型的)中随机获取一个元素,列表、元组、字符串都属于sequence。

代码语言:python
复制
random.randrange(10,100,2) 
#结果等效于
random.choice(range(10,100,2)

6.random.shuffle(x[,random])

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

代码语言:python
复制
p = ["Python","is", "powerful","simple”]  
random.shuffle(p)  

7.random.sample(sequence,k)

从指定序列中随机获取k个元素作为一个片段返回,\

sample函数不会修改原有序列

代码语言:python
复制
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  
slice = random.sample(list, 5) 
print(slice) 
print(list)

二、关键字参数

下面是一个判断传入的三条边长能否构成三角形的函数,在调用函数传入参数时,我们可以指定参数名,也可以不指定参数名,代码如下所示。

代码语言:python
复制
def is_triangle(a, b, c):
    print(f'a = {a}, b = {b}, c = {c}')
    return a + b > c and b + c > a and a + c > b


# 调用函数传入参数不指定参数名按位置对号入座
print(is_triangle(1, 2, 3))
# 调用函数通过“参数名=参数值”的形式按顺序传入参数
print(is_triangle(a=1, b=2, c=3))
# 调用函数通过“参数名=参数值”的形式不按顺序传入参数
print(is_triangle(c=3, a=1, b=2))

在没有特殊处理的情况下,函数的参数都是位置参数,也就意味着传入参数的时候对号入座即可,如上面代码的第7行所示,传入的参数值123会依次赋值给参数abc。当然,也可以通过参数名=参数值的方式传入函数所需的参数,因为指定了参数名,传入参数的顺序可以进行调整,如上面代码的第9行和第11行所示。

调用函数时,如果希望函数的调用者必须以参数名=参数值的方式传参,可以用命名关键字参数(keyword-only argument)取代位置参数。所谓命名关键字参数,是在函数的参数列表中,写在*之后的参数,代码如下所示。

代码语言:python
复制
def is_triangle(*, a, b, c):
    print(f'a = {a}, b = {b}, c = {c}')
    return a + b > c and b + c > a and a + c > b


# TypeError: is_triangle() takes 0 positional arguments but 3 were given
# print(is_triangle(3, 4, 5))
# 传参时必须使用“参数名=参数值”的方式,位置不重要
print(is_triangle(a=3, b=4, c=5))
print(is_triangle(c=5, b=4, a=3))

注意:上面的is_triangle函数,参数列表中的*是一个分隔符,*前面的参数都是位置参数,而*后面的参数就是命名关键字参数。

在函数的参数列表中可以使用可变参数*args来接收任意数量的参数,要看看*args是否能够接收带参数名的参数。

代码语言:python
复制
def calc(*args):
    result = 0
    for arg in args:
        if type(arg) in (int, float):
            result += arg
    return result


print(calc(a=1, b=2, c=3))

执行上面的代码会引发TypeError错误,错误消息为calc() got an unexpected keyword argument 'a',由此可见,*args并不能处理带参数名的参数。我们在设计函数时,如果既不知道调用者会传入的参数个数,也不知道调用者会不会指定参数名,那么同时使用可变参数和关键字参数。关键字参数会将传入的带参数名的参数组装成一个字典,参数名就是字典中键值对的键,而参数值就是字典中键值对的值,代码如下所示。

代码语言:python
复制
def calc(*args, **kwargs):
    result = 0
    for arg in args:
        if type(arg) in (int, float):
            result += arg
    for value in kwargs.values():
        if type(value) in (int, float):
            result += value
    return result


print(calc())                  # 0
print(calc(1, 2, 3))           # 6
print(calc(a=1, b=2, c=3))     # 6
print(calc(1, 2, c=3, d=4))    # 10

不带参数名的参数(位置参数)必须出现在带参数名的参数(关键字参数)之前,否则将会引发异常。例如,执行calc(1, 2, c=3, d=4, 5)将会引发SyntaxError错误,错误消息为positional argument follows keyword argument,翻译成中文意思是“位置参数出现在关键字参数之后”。

三、高阶函数的用法

如果希望上面的calc函数不仅仅可以做多个参数求和,还可以做多个参数求乘积甚至更多的二元运算,我们就可以使用高阶函数的方式来改写上面的代码,将加法运算从函数中移除掉,具体的做法如下所示。

代码语言:python
复制
def calc(*args, init_value, op, **kwargs):
    result = init_value
    for arg in args:
        if type(arg) in (int, float):
            result = op(result, arg)
    for value in kwargs.values():
        if type(value) in (int, float):
            result = op(result, value)
    return result

注意,上面的函数增加了两个参数,其中init_value代表运算的初始值,op代表二元运算函数。经过改造的calc函数不仅仅可以实现多个参数的累加求和,也可以实现多个参数的累乘运算,代码如下所示。

代码语言:python
复制
def add(x, y):
    return x + y


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


print(calc(1, 2, 3, init_value=0, op=add, x=4, y=5))      # 15
print(calc(1, 2, x=3, y=4, z=5, init_value=1, op=mul))    # 120

通过对高阶函数的运用,calc函数不再和加法运算耦合,所以灵活性和通用性会变强,这是一种解耦合的编程技巧,但是最初学者来说可能会稍微有点难以理解。需要注意的是,将函数作为参数和调用函数是有显著的区别的,调用函数需要在函数名后面跟上圆括号,而把函数作为参数时只需要函数名即可。上面的代码也可以不用定义addmul函数,因为Python标准库中的operator模块提供了代表加法运算的add和代表乘法运算的mul函数,我们直接使用即可,代码如下所示。

代码语言:python
复制
import operator

print(calc(1, 2, 3, init_value=0, op=operator.add, x=4, y=5))      # 15
print(calc(1, 2, x=3, y=4, z=5, init_value=1, op=operator.mul))    # 120

Python内置函数中有不少高阶函数,我们后面提到的filtermap函数就是高阶函数,前者可以实现对序列中元素的过滤,后者可以实现对序列中元素的映射,例如我们要去掉一个整数列表中的奇数,并对所有的偶数求平方得到一个新的列表,就可以直接使用这两个函数来做到,具体的做法是如下所示。

代码语言:python
复制
def is_even(num):
    return num % 2 == 0


def square(num):
    return num ** 2


numbers1 = [35, 12, 8, 99, 60, 52]
numbers2 = list(map(square, filter(is_even, numbers1)))
print(numbers2)    # [144, 64, 3600, 2704]

当然,要完成上面代码的功能,也可以使用列表生成式,列表生成式的做法更为简单优雅。

代码语言:python
复制
numbers1 = [35, 12, 8, 99, 60, 52]
numbers2 = [num ** 2 for num in numbers1 if num % 2 == 0]
print(numbers2)    # [144, 64, 3600, 2704]

四、Lambda函数

在使用高阶函数的时候,如果作为参数或者返回值的函数本身非常简单,一行代码就能够完成,那么我们可以使用Lambda函数来表示。Python中的Lambda函数是没有的名字函数,所以很多人也把它叫做匿名函数,匿名函数只能有一行代码,代码中的表达式产生的运算结果就是这个匿名函数的返回值。上面代码中的is_evensquare函数都只有一行代码,我们可以用Lambda函数来替换掉它们,代码如下所示。

代码语言:python
复制
numbers1 = [35, 12, 8, 99, 60, 52]
numbers2 = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, numbers1)))
print(numbers2)    # [144, 64, 3600, 2704]

通过上面的代码可以看出,定义Lambda函数的关键字是lambda,后面跟函数的参数,如果有多个参数用逗号进行分隔;冒号后面的部分就是函数的执行体,通常是一个表达式,表达式的运算结果就是Lambda函数的返回值,不需要写return 关键字。

如果需要使用加减乘除这种简单的二元函数,也可以用Lambda函数来书写,例如调用上面的calc函数时,可以通过传入Lambda函数来作为op参数的参数值。当然,op参数也可以有默认值,例如我们可以用一个代表加法运算的Lambda函数来作为op参数的默认值。

代码语言:python
复制
def calc(*args, init_value=0, op=lambda x, y: x + y, **kwargs):
    result = init_value
    for arg in args:
        if type(arg) in (int, float):
            result = op(result, arg)
    for value in kwargs.values():
        if type(value) in (int, float):
            result = op(result, value)
    return result


# 调用calc函数,使用init_value和op的默认值
print(calc(1, 2, 3, x=4, y=5))    # 15
# 调用calc函数,通过lambda函数给op参数赋值
print(calc(1, 2, 3, x=4, y=5, init_value=1, op=lambda x, y: x * y))    # 120

注意上面的代码中的calc函数,它同时使用了可变参数、关键字参数、命名关键字参数,其中命名关键字参数要放在可变参数和关键字参数之间,传参时先传入可变参数,关键字参数和命名关键字参数的先后顺序并不重要。

有很多函数在Python中用一行代码就能实现,我们可以用Lambda函数来定义这些函数,调用Lambda函数就跟调用普通函数一样,代码如下所示。

代码语言:python
复制
import operator, functools

# 一行代码定义求阶乘的函数
fac = lambda num: functools.reduce(operator.mul, range(1, num + 1), 1)
# 一行代码定义判断素数的函数
is_prime = lambda x: x > 1 and all(map(lambda f: x % f, range(2, int(x ** 0.5) + 1)))

# 调用Lambda函数
print(fac(10))        # 3628800
print(is_prime(9))    # False

上面使用的reduce函数是Python标准库functools模块中的函数,它可以实现对数据的归约操作,通常情况下,过滤(filter)、映射(map)和归约(reduce)是处理数据中非常关键的三个步骤,而Python的标准库也提供了对这三个操作的支持。all函数是Python内置函数,如果传入的序列中所有布尔值都是Trueall函数就返回True,否则all函数就返回False

Python中的函数可以使用可变参数*args和关键字参数**kwargs来接收任意数量的参数,而且传入参数时可以带上参数名也可以没有参数名,可变参数会被处理成一个元组,而关键字参数会被处理成一个字典。Python中的函数是一等函数,可以赋值给变量,也可以作为函数的参数和返回值.

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、高级函数
    • 1.时间函数
      • 2.日历函数
        • 3.随机数函数
        • 二、关键字参数
        • 三、高阶函数的用法
        • 四、Lambda函数
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档