30天拿下Python之函数

概述

在上一节,我们介绍了Python的数据类型,包括:数字、字符串、列表、元组、集合、字典等内容。在本节中,我们将介绍Python的函数。在Python中,函数是一段可以重复使用的代码块,它可以提高代码的可重用性和可维护性,是编程中非常重要的概念。
在C/C++、Java等其他编程语言中,基本都存在函数的概念。那么,为什么要使用函数呢?因为函数具有以下优点。
可定制性:函数可以根据需求定制,以满足不同的功能需求。
可重用性:函数可以重复使用,避免重复编写相同的代码。
可维护性:函数可以降低代码的复杂性,提高代码的可维护性。

函数的定义

在Python中,可以使用def关键字定义一个函数,其格式如下:

def function_name(parameters):
    """docstring"""
    function_body

其中,function_name是函数的名称,parameters是函数的参数列表,最后面是冒号,冒号后面的内容需要缩进。docstring是函数的文档字符串,用于描述函数的作用和用法。function_body是函数的主体部分,包含函数的逻辑代码。
函数的参数放在小括号里面,参数可以有一个或多个,也可以没有,多个参数之间使用逗号进行分隔。

# 没有参数
def my_print():
    print('hello')

# 一个参数
def print_text(text):
    print('hello', text)

# 多个参数
def print_sum(x, y):
    print('sum:', x + y)

函数可以通过return语句返回一个值。如果函数没有return语句,或者return语句没有跟任何值,则函数返回默认的None。

# 不带return,默认返回None
def test1():
    print('hello Hope')

# return没有跟任何值,默认返回None
def test2():
    print('hello world')
    return

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

函数的调用

定义函数后,可以通过函数名加上参数列表的方式调用函数。调用函数时,将实际参数传递给函数的参数列表。

# 统计文本中的单词数量
def count_words(text):
    words = text.split()
    count = len(words)
    return count

def show_info(name, age):
    print('name is', name, ', age is', age)

# 调用上面定义好的函数
count = count_words('hello Hope')
# 输出:2
print(count)
# 输出:name is Mike , age is 16
show_info('Mike', 16)

参数的传递

在上一节我们曾提到,数字、字符串、元组属于不可变数据类型,列表、集合、字典属于可变数据类型。
当函数的参数为不可变数据类型时,参数的传递与C++中的值传递类似。比如:有一个函数func(a),传递的只是a的值,没有影响a对象本身。如果在func(a)内部修改a的值,则是新生成一个a的对象,修改后func外部的a不会受到影响。

def test1(a):
    # 输出:66
    print(a)
    a = 100
    # 输出:100
    print(a)

a = 66
test1(a)
# 不可变数据类型,仍然输出:66
print(a)

当函数的参数为可变数据类型时,参数的传递与C++中的引用传递类似。比如:有一个函数func(a),传递的是a的地址。如果在func(a)内部修改a的值,修改后func外部的a也会受到影响。

def test1(a):
    # 输出:['C', 'S', 'D']
    print(a)
    a.append('N')
    # 输出:['C', 'S', 'D', 'N']
    print(a)

a = ['C', 'S', 'D']
test1(a)
# 可变数据类型,输出:['C', 'S', 'D', 'N']
print(a)

函数的参数主要有五种不同的类型:必需参数、默认参数、不定长参数、强制关键字参数、强制位置参数,下面分别进行介绍。
必需参数:调用时,必须传递的参数;如果不传递,运行时会引发TypeError异常。必须参数既可以按照位置逐一传递,也可以使用关键字指定的方式传递(此时不用与定义时的参数顺序保持一致)。

def show_info(name, age, gender):
    print(f'{name}, {gender}, is {age} years old')

# 输出:Mike, Male, is 25 years old
show_info('Mike', 25, 'Male')
# 输出:Tom, Female, is 32 years old
show_info('Tom', gender='Female', age=32)
# 报错:missing 1 required positional argument: 'gender'
show_info('Jim', 28)

默认参数:定义时,参数给定了默认值;调用时,可以传递该参数,也可以不传递该参数,不传递则使用默认值。

def greet(name = 'Hope'):
    print(f'Hello, {name}')
  
# 输出:Hello, Hope
greet()
# 输出:Hello, World
greet('World')

不定长参数:在Python中,可以使用两种方式定义不定长参数。一是使用一个星号()作为参数前缀,将该参数定义为不定长位置参数;该参数可以接收任意数量的参数,并将它们打包成一个元组(tuple)传递给函数。二是使用两个星号(*)作为参数前缀,将该参数定义为不定长关键字参数;该参数可以接收任意数量的关键字参数,并将它们打包成一个字典(dict)传递给函数。

# 一个星号的不定长参数
def func1(*args):
    for arg in args:
        print(arg)

# 依次输出:66 88 99
func1(66, 88, 99)
# 依次输出:Hello Hope
func1('Hello', 'Hope')

# 两个星号的不定长参数
def func2(text, **kwargs):
    print(text)
    for key, value in kwargs.items():
        print(f'{key}: {value}')

# 依次输出:info: name: Lily age: 16 city: BeiJing
func2('info:', name='Lily', age=16, city='BeiJing')

强制关键字参数:只能以关键字形式来指定的参数,从而确保调用该函数的代码读起来会比较明确。定义函数时,如果单独出现星号(*),则星号后的参数必须用关键字传入。

def my_sum(a, b, *, c):
    return a + b + c

# c为强制关键字参数,必须以关键字方式指定
my_sum(1, 2, c = 3)
# 运行时报错:my_sum() takes 2 positional arguments but 3 were given
my_sum(1, 2, 3)

强制位置参数:只能以位置形式,不能以关键字形式来指定的参数。定义函数时,如果单独出现斜杠(/),则斜杠前的参数必须用位置形式传入。

def my_sum(a, b, /, c):
    return a + b + c

# a、b为强制位置参数,必须以位置方式指定
my_sum(1, 2, 3)
# 运行时报错:my_sum() got some positional-only arguments passed as keyword arguments: 'b'
my_sum(1, b = 2, c = 3)

lambda函数

lambda函数是一种没有函数名称的匿名函数或小型函数,通常用于短小的、临时性的、或者作为高阶函数的参数(比如:map()、filter()等)。
lambda函数的语法格式为:lambda arguments : expression。
其中,arguments是一个函数参数列表,由一个或多个参数组成,多个参数之间使用逗号进行分隔。expression是一个表达式,当有多个参数时,表达式中必须使用参数对应的顺序。
在下面的例子中,定义了一个lambda函数my_add,接收两个参数x和y,并返回它们的和,最后通过调用my_add(66, 99)来执行这个函数。

my_add = lambda x, y: x + y
# 输出:165
print(my_add(66, 99))

再来看看在高阶函数filter中使用lambda函数的例子。

data = [12, 25, 7, 32, 21]
# 找出列表中所有大于20的数
result = filter(lambda x: x > 20, data)
# 输出:[25, 32, 21]
print(list(result))

总结一下,lambda函数具有以下优点:
语法简洁:lambda函数使用简洁的语法,可以在一行代码中定义简单的函数。
匿名函数:lambda函数是匿名函数,不需要指定函数名称,这使得它们可以作为临时函数在代码中快速定义。
短小函数:lambda函数通常定义的是短小的函数,这使得它们在处理简单的任务时非常方便。
高阶函数参数:lambda函数常作为高阶函数的参数,这使得它们可以与其他函数配合使用,实现更加灵活和定制化的操作。
提高代码可读性:在一些情况下,使用lambda函数可以使代码更加简洁、易于理解。
提高执行效率:与普通函数相比,lambda函数的执行效率更高。
不过需要注意的是,虽然lambda函数在某些情况下非常有用,但在处理复杂任务或需要重复使用的功能时,还是建议使用完整的函数定义。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容