Python:函数

1. 函数的定义与使用

def greet_user():
    """显示简单的问候语""" 
    print("Hello!") 
    
greet_user() #Hello!

这个示例演示了最简单的函数结构。使用关键字def来告诉Python你要定义一个函数。

定义函数时,要向Python指出了函数名,还可能在括号内指出函数需要的参数。

在这里,函数名为greet_user() ,它不需要任何参数,因此括号是空的(即便如此,括号也必不可少)。

最后,定义以冒号结尾。

函数在进行使用时必须要带上“()”,否则无法使用。

2. 函数的参数

2.1 位置参数

你调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。

为此,最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参。

def describe_pet(animal_type, pet_name): 
    """显示宠物的信息""" 
    print("\nI have a " + animal_type + ".") 
    print("My " + animal_type + "'s name is " + pet_name.title() + ".") 
    
#相同的位置相对应,因此位置实参的实参位置很重要。
describe_pet('hamster', 'harry')
"""I have a hamster.
My hamster's name is Harry."""

2.2 默认参数

编写函数时,可给每个形参指定默认值 。在调用函数中给形参提供了实参时,Python将使用指定的实参值;

否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参。

def describe_pet(pet_name, animal_type='dog'):
    """显示宠物的信息""" 
    print("\nI have a " + animal_type + ".") 
    print("My " + animal_type + "'s name is " + pet_name.title() + ".") 

# 调用这个函数时,如果没有给animal_type 指定值,Python将把这个形参设置为'dog'。
describe_pet(pet_name='willie')
"""I have a dog. 
My dog's name is Willie."""

由于给animal_type 指定了默认值,无需通过实参来指定动物类型,因此在函数调用中只包含一个实参——宠物的名字。

然而,Python依然将这个实参视为位置实参,因此如果函数调用中只包含宠物的名字,这个实参将关联到函数定义中的第一个形参。

这就是需要将pet_name 放在形参列表开头的原因所在。

因此上述结果也可用另种方式表示:

describe_pet('willie')

如果要描述的动物不是小狗,可使用类似于下面的函数调用:

describe_pet(pet_name='harry', animal_type='hamster')

由于显式地给animal_type 提供了实参,因此Python将忽略这个形参的默认值。

2.3 关键字参数

关键字实参是传递给函数的名称对。你直接在实参中将名称和值关联起来了,因此向函数传递实参时不会混淆。

def describe_pet(animal_type, pet_name): 
    """显示宠物的信息""" 
    print("\nI have a " + animal_type + ".") 
    print("My " + animal_type + "'s name is " + pet_name.title() + ".") 
    
describe_pet(animal_type='hamster', pet_name='harry')
"""
I have a harry. 
My harry's name is Hamster."""

关键字实参的实参顺序不重要。

2.4 可变参数

简单可变参数:*args

有时候,你预先不知道函数需要接受多少个实参,Python允许函数从调用语句中收集任意数量的实参。

def make_pizza(*toppings): 
    """打印顾客点的所有配料""" 
    print(toppings) 

make_pizza('pepperoni') #('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese') #('mushrooms', 'green peppers', 'extra cheese')

形参名toppings 中的星号让Python创建一个名为toppings 的空元组,并将收到的所有值都封装到这个元组中。

可以将位置参数、关键字参数和可变参数相结合。

此时必须在函数定义中将接纳任意数量实参的形参放在最后。

Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。

def make_pizza(size, *toppings):
    """概述要制作的比萨""" 
    print("\nMaking a " + str(size) + "-inch pizza with the following toppings:") 
    for topping in toppings:
        print("- " + topping) 
        
make_pizza(16, 'pepperoni') 
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

"""Making a 16-inch pizza with the following toppings: 
- pepperoni 
Making a 12-inch pizza with the following toppings:
- mushrooms 
- green peppers 
- extra cheese"""

键值对可变参数:**kwargs

有时候,需要接受任意数量的实参,但不知道这些参数是什么类型的数据。

在这种情况下,可将函数参数编写成能够接受任意数量的键值对。

def build_profile(first, last, **user_info):
    """创建一个字典,其中包含我们知道的有关用户的一切"""
    profile = {}
    profile['001'] = first
    profile['002'] = last
    for key, value in user_info.items():
        profile[key] = value
        return profile

user_info = {'003':'王五'}
user_profile = build_profile('张三', '李四', **user_info)
print(user_profile) #{'001': '张三', '002': '李四', '003': '王五'}

形参user_info 中的两个星号让Python创建一个名为user_info 的空字典,并将收到的所有名称—值对都封装到这个字典中。

在这个函数中,可以像访问其他字典那样访问user_info 中的键值对。

编写函数时,你可以以各种方式混合使用位置实参、关键字实参和任意数量的实参。

3. 函数返回值

3.1 简单返回值

def get_formatted_name(first_name, last_name): 
    """返回整洁的姓名"""  
    full_name = first_name + ' ' + last_name 
    return full_name.title()  
musician = get_formatted_name('jimi', 'hendrix') 
print(musician) #Jimi Hendrix  

3.2 返回字典

函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。

def build_person(first_name, last_name):
    """返回一个字典,其中包含有关一个人的信息""" 
    person = {'first': first_name, 'last': last_name} 
    return person 
musician = build_person('jimi', 'hendrix') 
print(musician) #{'first': 'jimi', 'last': 'hendrix'}

3.3 返回值特点

  1. 若返回了x个结果,且有x个接收值,则返回值与接收值之间一一对应
  2. 若返回了x个结果,但只有1个接收值,则返回值形成元组赋值给唯一的接收值

4. 变量与内部函数

4.1 局部变量与全局变量

局部变量

声明在函数内部,仅限函数内部使用

全局变量

声明在函数外部,所有变量可以访问

局部变量可以在函数内部修改,当全局变量不可变时,不可随意在函数内部修改,要使用global

例如list全局变量是可变的,字符串全局变量是不可变的

4.2 内部函数

内部函数是指定义在函数内部的函数

内部函数的特点:

  1. 内部函数可以访问外部函数的变量
  2. 内部函数可以修改外部函数的可变变量
  3. 内部函数修改全局变量的不可变变量时,需要在内部函数声明:global 变量名
  4. 内部函数修改外部函数的不可变的变量时,需要在内部函数中声明:nonlocal 变量名
  5. locals()查看本地变量有哪些,以字典的形式输出
  6. globals()查看全局变量有哪些,以字典形式输出,存在系统键值对
def func1():
    # 声明变量
    n = 100 # 局部变量
    list = [1,3,6,0]

    def func2():
        # 使用nonlocal使内部函数可以使用局部不可变变量
        nonlocal n
        y = 0
        for i in list:
            list[y] += n
            y += 1

        n += 1

    func2()
    print(n)
    print(list)

func1()
#101
#[101, 103, 106, 100]
# 全局变量
a = 100
print(globals())

def func():
    #局部变量
    b = 99

    def func1():
        # 对于全局变量a的声明必须在内部函数中
        global a
        nonlocal b
        c = 98

        c += 1
        b += 1
        a += 1

        print(c)
        print(b)
        print(a)

    func1()
    print(locals())#{'func1': <function func.<locals>.func1 at 0x000001B927A290D8>, 'b': 100}

func()
"""99
100
101"""

5. 函数的闭包

5.1 闭包的概念

外部函数通过return将内部函数返回的形式叫做闭包

形成条件:

  1. 外部函数中定义了内部函数
  2. 外部函数是有返回值
  3. 返回的值是:内部函数名
  4. 内部函数引用了外部函数的变量
def func1():
    a = 100
    def func2():
        b = 99
        print(a,b)

    return func2

x = func1()
print(x) #<function func1.<locals>.func2 at 0x00000273B56290D8>
x() #100 99

5.2 闭包保存参数状态

def func1(a, b):
    c = 1
    def func2():
        s = a + b + c
        print(s)

    return func2

x = func1(10,4)
y = func1(3, 7)

y() #11
x() #15

6. 装饰器

6.1 装饰器的概念

装饰器的特点:

  1. 函数作为参数传递给另一函数
  2. 要有闭包的特点
  3. 原函数func1带参数,则wrapper函数必须带参数,并传给内部的func1
def decorate(func):
    a = 100
    print('进行操作1')

    def wrapper(): #若参数为(*args,**kwargs)则为万能装饰器
        func()
        print("进行操作2")

    print('进行操作3')

    return wrapper

# 使用装饰器
@decorate
def func1():
    print('进行操作4')

"""
进行操作1
进行操作3
"""
func1()
"""
进行操作1
进行操作3
进行操作4
进行操作2
"""
"""
1.func1被装饰函数
2.将被装饰函数作为参数传给装饰器decorate
3.执行decorate函数
4.将decorate函数返回值又赋值给house
"""

6.2 装饰器的参数问题

原函数带参数

原函数的参数问题分为以下几种情况:

  1. 原函数带一个参数:wrapper函数必须带参数
  2. 原函数带未知个参数:wrapper函数带参数*args
  3. 原函数带默认参数:wrapper函数带参数**kwargs
  4. 无论原函数带什么参数:都可使用(args,*kwargs)

装饰器带参数

带参数的装饰器是三层的,最外层的函数负责接收装饰器参数,里面的内容还是原装饰器的内容

# 装饰器带参数
def outer(a): # 第一层
    def decorate(func): # 第二层
        def wrapper(*args,**kwargs): # 第三层
            func(*args)
            print('---->铺地砖{}快'.format(a))

        return wrapper # 返回出来的是:第三层
    return decorate # 返回出来的是:第二层

@outer(10)
def house(time):
    print('我{}日期拿到房子'.format(time))

@outer(100)
def stree():
    print('修建街道')

house('2020-07-18')
stree()
"""我2020-07-18日期拿到房子
---->铺地砖10快
修建街道
---->铺地砖100快"""

6.3 多层装饰器

一个原函数可使用多个装饰器修饰,先执行最近的装饰器,将其内部函数作为另一个装饰器的参数进行执行下一个装饰器

7. 匿名函数

7.1 匿名函数的格式

lambda 参数1,参数2 : 运算

# 匿名函数
s = lambda a,b : a + b

print(s)
result = s(1,2) #<function <lambda> at 0x00000176A4AFFAF8>
print(result) #3

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

推荐阅读更多精彩内容

  • 1.1.函数定义 1.1.1.定义一个函数 1.1python定义函数用def关键字,一般格式如下 1.2函数名的...
    Rolle_Wang阅读 477评论 0 0
  • 1.定义一个函数 定义一个函数需要5个部分: def告诉Python,用户在自定义函数 function_name...
    陶不渊阅读 432评论 0 0
  • 第5章 函数和函数式编程 5.1 引言函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数...
    VIVAFT阅读 947评论 0 5
  • 一函数定义 1内置函数 Python内置了很多有用的函数,我们可以直接调用。不像C#中调用函数,需要先实例化类,再...
    凌雲木阅读 355评论 0 2
  • 一个寻常的早上,我坐在小凳子上,她背对窗户,刚洗了头发准备换衣服去上班。逆光的影像蒙了一层牛乳,线条虚化——湿的头...
    我有百合阅读 179评论 0 0