Day9~11—总结 函数

函数

1、什么是函数

是实现某一特定功能的代码块的封装

2、函数的分类

系统函数(内置函数) - 系统已经实现了的函(已经造好的机器),只需要调用就可以了
print函数 input函数 len函数 sum函数 max函数等等

自定义函数:程序员自己声明的函数(自己造机器)

3、函数的声明(定义)

1)语法
def 函数名(形参列表):
"""
函数说明文档
"""
函数体

2)说明
def —— python声明函数的关键字
函数名 —— 和变量名一样 见名知意 看到函数名大概知道是用来做什么的
() —— 固定写法
形参列表 —— 变量1, 变量2, 变量3···变量名的个数可以是 0个或多个
它是将函数外面的值传递到函数里面
: —— 固定写法
函数体 —— 和def保持一个缩进的,实现函数功能的一条或者多条语句

3)初学者声明函数的步骤
一、确定函数的功能
二、根据功能确定函数名
三、确定形参,看实现函数的功能需不需要从外面传值,如果需要传值需要几个
四、实现函数功能
五、确定返回值

!!!!!)注意:函数在声明的时候,函数体不会执行


练习:写一个函数求两个数和

# 写一个函数求两个数和
def t_sum(x, y):
    """
    函数说明文档(功能说明)
    :param x:  (参数说明)
    :param y:
    :return:    (返回值说明)
    """
    print('求和')
    print(x+y)

练习:声明一个函数 实现求1+2+3+。。。n

# 声明一个函数 实现求1+2+3+。。。n
def sum1(n):
    """
    求1+2+3+。。。n
    :param x:
    :return:
    """
    i = 0
    for x in range(n+1):
        i += x
    print(i)

sum1(10)

4、函数的调用 使用

1)语法:
函数名(实参列表)

2)说明
函数名 —— 必须是已经声明过的函数
() —— 固定写法
实参列表 —— 数据1, 数据2··· 给形参赋值

同一个函数可以调用多次

3)函数的调用过程(重要*********)

一、回到函数声明的位置
二、用实参给形参赋值 (传参)要保证每一个形参都要有值
三、执行函数体
四、获取返回值
五、回到函数调用的位置,接着往后执行



函数的参数

1、位置参数、关键字参数

调用函数的时候 根据实参的写法分为位置参数、关键字参数

  • 位置参数:让实参的顺序与形参一一对应,用逗号隔开
  • 关键字参数:以'形参名1 = 值1, 形参名2 = 值2····' 格式来确定实参
  • 位置参数+关键字参数:位置参数必须写在关键字参数前

2、参数默认值

声明函数的时候,可以给形参赋默认值
有默认值的形参在函数调用的时候,可以不用给形参赋值
注意:声明的时候,有默认值的参数必须放在最后,当跳过有默认值的参数赋值时,必须使用关键字参数

def func2(a, b=12, c=19):
    print(a, b, c)

# 调用函数只给a和c赋值,b使用默认值

func2(13, c=23)

3、参数的类型说明

python中类型只有说明的作用,没有约束的作用,有两种方法:
1)参数赋默认值
2)参数名:类型

4、不定长参数 - 形参的参数不确定

  • 声明函数的时候,在形参前面加*星号,那么这个参数就变成不定长参数,
    同时可以接收多个实参(将这个参数变成元祖)必须用位置实参数

  • 声明函数的时候,在形参的前面加**两个星号,那么这个参数也会变成不定长参数,
    同时可以接收多个实参(将这个参数变成字典)必须用关键字实参数,关键字是key

注意:定长参数必须在不定长参数前面
不带星号的参数要放在带星号参数的前面


练习: 练习:写一个函数,按指定方式计算多个数字的结果
operation('+', '23', '24') ——> 23 + 24
operation('-', '23', '24')

def operation(ex, *a):
    if ex == '+':
        num1 = 0
        for x in range(len(a)):
            num1 += x
        print(num1)
    elif ex == '*':
        num1 = 1
        for x in range(len(a)):
            num1 *= x

练习:写一个函数求多个数的和 既可以使用位置传参,又可以使用关键字传参

def func1(*args, **kwargs):
    """
    求多个数的和
    :param args:不定长参数 位置参数 整型 元祖
    :param kwargs: 不定长参数 关键字参数 字典
    :return:
    """
    sum1 = 0
    print(sum(args))
    for key in kwargs:
        sum1 += kwargs[key]
    print(sum1 + sum(args))

func1(2, 3, 4, a=2, b=3, c=4)


函数的返回值

1、什么是函数的返回值

返回值就是return关键字后面表达式的值,就是函数调用表达式的值

return
函数体中的关键字 只能出现在函数体里

作用:

  • 结束函数
  • 确定函数返回值

调用函数:执行函数体 获取返回值

函数调用过程: 重要
一、回到函数声明的位置
二、用实参给形参赋值 (传参)要保证每一个形参都要有值
三、执行函数体
四、获取返回值
执行完函数体:函数体执行完、执行过程中遇到return
确定函数返回值:执行函数的过程中有没有遇到return,
如果遇到了,return后表达式的值就是函数的返回值
没有遇到return,函数返回值就是None
五、回到函数调用的位置,接着往后执行(这个时候函数调用表达式的值就是函数的返回值)

2、什么时候需要返回值

如果实现函数的功能,会产生新的数据,就把这个数据作为返回值
return 返回值1,返回值2



匿名函数

什么是匿名函数

匿名函数就是没有名字的函数

1)语法:
lambda 参数列表:返回值

2)说明
lambda - 关键字
参数列表 - 相当于普通函数形参列表
: - 固定写法
返回值 - 相当于普通函数函数体中的return 不能是赋值语句·

注意:

  • 匿名函数本质还是函数,函数中的语法绝大多数是适用的
  • 匿名函数能做的事情,普通函数都可以做。只是匿名函数简洁
  • 不支持通过类型名对参数类型说明

练习:匿名函数求两个数的和

# 匿名函数是一个类型为function的值
fun1 = lambda a, b=1: a+b

print(fun1(1, 2))
print(fun1(a=1, b=2))
print(fun1(1))


函数中的变量

1.变量的作用域

指的是变量的使用范围
全局变量、局部变量

2.全局变量

只要是没有声明在函数中的变量都是全局变量
全局变量的作用域是从变量声明开始到整个py文件结束

3.局部变量

声明在函数中的变量都是局部变量
局部变量的作用域就是从变量声明到函数结束
注意:形参也是局部变量

当调用函数的时候,系统会自动在内存的栈区间为这个函数开辟一个独立的内存区域
用来保存在函数中声明的变量或者产生的数据。当函数调用结束后,这块内存区域会自动销毁

4. global 和 nonlocal

global - 在函数中声明一个全局变量 只能在函数中使用
global 变量名
变量名 = 值

nonlocal - 在局部的局部中修改一个局部变量的值
nonlocal 局部变量名
局部变量名 = 值

x1 = 100


def func4():
    # x1 = 200  这个x1是局部变量
    global x1  # 说明后面的x1是一个全局变量
    x1 = 200
    print('函数中', x1)


func4()
print('函数外', x1)

print('0-------------')


def func5():
    x2 = 100

    def func6():
        # x2 = 200
        nonlocal x2
        x2 = 200
        print('函数5的函数6中', x2)
    func6()

    print('函数5中', x2)


func5()


函数作为变量

1.函数作为变量

python中声明函数其实就是声明一个类型是function的变量
函数名就是变量名

所以普通变量能做的事情函数都可以做

2.一个变量可以给另一个变量赋值

def func1():
    return 100

c = func1
c()
print(c())

func1 = 12.5
print(func1)

3.一个变量可以作为一个容器的元素

a = 10            #声明一个变量,类型是整型
print(type(a))

# 声明一个变量,类型是function
def func2():
    print('这是函数2')
    return 100

print(type(func2))
list1 = [a, func2, func2()]
print(list1)
print('0:', list1[0] // 3)
print('1:', list1[1]())    # print('1:', func2())  -> print('1:', 100)

练习:

list2 = []
for i in range(5):
    def func(n):
        return i * 2
    list2.append(func)


list3 = []
for i in range(5):
    list3.append(lambda x: x*i)


print(list3[0](2), list3[1](2), list3[2](2))
"""
list2 = []
i = 0 ~ 4
i = 0:  func, list2 = [func]
i = 1:  func, list2 = [func, func]
...
i = 4: list2 = [func,func,func,func,func]
"""
# list2[0](3), list2[1](3), list2[2](3)
# func, func, func
# None, None, None
# 0, 2, 3
# 8, 8, 8
print(list2)
print(list2[0](3), list2[1](3), list2[2](3))

4. 变量可以作为函数的参数

函数作为函数的参数(实参高阶函数)

def func1(fn, fn2):
    # fn = func11
    # fn2 = func12
    fn()   # func11(),  None
    print(fn2(3) / 4)  # print(9/4)


def func11():
    print('这是一个函数')


def func12(n):
    # n = 3
    return n**2


print(func1(func11, func12))   # print(None)

应用: sort函数 (排序)

nums = [1, 23, 34, 32, 12]
nums.sort()      # 从小到大排序
print(nums)

序列.sort函数中有个参数key,这个参数要求传一个函数,并且函数有一个参数和一个返回值
参数就是序列中的元素,返回值就是排序比较的对象

all_stu = [
    {'name': 'dd', 'age': 12, 'score': 32},
    {'name': 'ad', 'age': 15, 'score': 41},
    {'name': 'sd', 'age': 13, 'score': 36},
    {'name': 'cd', 'age': 11, 'score': 72}
]

def compare(item):
    return item['age']


all_stu.sort(key=compare)
all_stu.sort(key=lambda item: item['age'])
print(all_stu)
all_message = [
    ('张', 'python1902001'),
    ('李', 'python1902108'),
    ('王', 'python1902046')
]

all_message.sort(key=lambda item: item[1], reverse=True)
print(all_message)

all_message.sort(key=lambda item: item[1][-1])
print(all_message)

5.变量作为函数的返回值

将一个函数作为函数的返回值(返回值高阶函数)

def func1():

    def temp(*nums):
        return sum(nums)
    return temp


print(func1()(1, 2, 3, 4))


迭代器 (iter)

1.什么是迭代器(iter)

是容器型数据类型(可以同时存储多个数据),但是想要获取、查看迭代器中元素的值
只能将元素取出来,取出来的元素,在迭代器中就不存在了,去的时候在只能从前往后一个一个的取,不能跳着取

2.迭代器中的元素

迭代器只能通过类型转换将其他容器转换成迭代器,或者通过生成器生成
转换 - 所有序列都可以转换成迭代器。迭代器中的元素可以是任何类型的数据

3.获取元素 -

迭代器获取元素,无论以什么样的方式获取获取后,这个元素在迭代器中就不存在了

    1. next(迭代器) - 获取迭代器最上的数据
    1. 遍历获取每一个元素
 # 1) next(迭代器)  - 获取迭代器最上的数据

iter2 = iter('hello')
print(next(iter2))
print(next(iter2))
print(next(iter2))
print(next(iter2))
print(next(iter2))
# print(next(iter2))  错误 # StopIteration

# 2) 遍历获取每一个元素

iter3 = iter('hello')
for x in iter3:
    print(x)


生成器

1.什么是生成器

生成器本质是迭代器,迭代器不一定是生成器
调用一个带有yield关键字的函数就能得到一个生成器. yield只能在函数体里

def func1():
    print('--')
    return 100
    yield


gen1 = func1()
print(gen1)

2.生成器的元素

生成器获取元素的方式和迭代器一样 next()和 遍历

    1. 生成器元素的个数:看执行完生成器对应的函数会遇到几次yield
    1. 元素的值:看yield后表达式的值

3.生成器产生数据的原理

当获取生成器的元素的时候,会执行生成器对应的函数,从开始执行到yield为止,并且将yield后面的数据作为元素返回
并且记录结束位置,下次再获取元素的时候,从上次结束的位置接着往后执行,直到遇到yield,并且将yield后面的数据作为元素返回
以此类推。
如果函数从开始到结束时都没有遇到yield,就获取不到元素。next会报错 for循环会结束

def func2():
    print('===')
    yield 200


gen3 = func2()
print(next(gen3))

生成式

本质还是生成器 只是写法更简洁

写法:
语法1.
(表达式 for 变量 in 序列)

展开
def func():
for 变量 in 序列:
yield 表达式
func()

() - 固定写法
表达式 - 除了赋值以外的任何语句,如数据、变量、运算表达式、函数调用表达式
一般和后面的变量有联系
for in - for循环

语法2.
(表达式 for 变量 in 序列 if 条件语句)

展开
def func():
for 变量 in 序列:
if 条件语句:
yield 表达式

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

推荐阅读更多精彩内容

  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,521评论 0 5
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,729评论 0 38
  • 1、c语言的函数有以下特点: (1)才源程序由函数组成,一个主函数main()+若干其他函数 C程序中的函数类似文...
    滕王阁序阅读 1,329评论 0 6
  • 原文地址:C语言函数调用栈(一)C语言函数调用栈(二) 0 引言 程序的执行过程可看作连续的函数调用。当一个函数执...
    小猪啊呜阅读 4,585评论 1 19
  • 函数只定义一次,但可能被执行或调用任意次。JS函数是参数化的,函数的定义会包括一个称为形参的标识符列表,这些参数在...
    PySong阅读 514评论 0 0