Python小白学习笔记第7课:Python函数(2024版)

204次阅读
没有评论

共计 5909 个字符,预计需要花费 15 分钟才能阅读完成。

Python 小白学习笔记第 6 课:Python 表达式和语句(2024 版)

函数其实就是一段重用的代码,给这段代码起一个名字,这就是函数定义。使用函数可以将功能上相对独立且会被重复使用的代码封装起来,当需要这些代码的时候,不用把重复的代码再写一遍,而是通过调用函数实现对既有代码的复用。

Python 自带的函数叫做“内置函数”,也就是 Python 帮我们提前写好的,我们直接拿来用就行。

内置函数有很多,具体可查看官方文档:https://docs.python.org/zh-cn/3/library/functions.html

输入输出

其实,我们之前一直在使用的print(),就是内置函数,用来将内容输出到屏幕上。在 Python 中,与之对应的还有一个函数input(),用来获取键盘输入。

name = input("请输入您的姓名:")  # 提示用户输入名字
age = input("请输入您的年龄:")  # 提示用户输入年龄
print("欢迎光临,", name)  # 打印欢迎信息
print("您今年", age, "岁了!")  # 打印年龄信息

"""
请输入您的姓名:张三
请输入您的年龄:18
欢迎光临, 张三
您今年 18 岁了!"""

自定义函数

内置函数虽然不少,但毕竟数量有限,只靠内置函数是不可能实现所有功能的。因此,编程中往往需要将频繁使用的代码封装为自定义函数。语法格式如下:

def 函数名(参数):
    函数体
    return 返回值

定义完函数,就可以在程序的任何地方使用 函数名 () 运行这段代码,即函数调用。

def my_print():
    print("自定义输出函数")

my_print()  # 自定义输出函数

函数参数

我们把函数定义时的参数称为形式参数(形参),函数调用时的参数称为实际参数(实参)。

位置参数

def my_print(n):
    print("*" * n)

my_print(5)  # *****
my_print()  # 报错

函数定义时有几个参数,函数调用时就必须传入几个参数,否则会报错,除非参数有默认值。

关键字参数

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

def my_print(name, age):
    print("欢迎光临,", name)
    print("您今年", age, "岁了!")

my_print(age=18, name="张三")

默认参数

函数调用时,默认参数的值如果没有传入,则使用默认值。

def my_print(n=5):
    print("*" * n)

my_print()  # *****
my_print(10)  # **********

Python 在创建函数(未执行)时,如果函数的参数有默认值,则会在函数内部创建一块区域维护这个默认值。

在特定情况【默认参数的值是可变类型 list/dict/set】和【函数内部会修改这个值】下,参数的默认值有坑:

def my_print(a1, a2=[1, 2]):
    a2.append(666)
    print(a1, a2)

my_print(100)  # 100 [1, 2, 666]
my_print(200)  # 200 [1, 2, 666, 666]
my_print(300, [888, 777])  # 300 [888, 777, 666]
my_print(300)  # 300 [1, 2, 666, 666, 666]

动态参数

即定义函数时在形参位置用 * 或 ** 可以接任意个参数。

def my_print(*args, **kwargs):
    print(args, kwargs)

my_print("姓名", "年龄", name="女", age=18)  # ('姓名', '年龄') {'name': '女', 'age': 18}

在执行函数时,实参也可以用* 或 **

def my_print(a1, a2):
    print(a1, a2)

my_print(*[11, 22])  # 结果为:11 22
my_print(**{"a1": 11, "a2": 22})  # 结果为:11 22

形参和实参都用* 和 **

def my_print(*args, **kwargs):
    print(args, kwargs)

my_print(*[11, 22], **{"k1": 1, "k2": 2})  # 结果为:(11, 22) {'k1': 1, 'k2': 2}

参数组合

在 Python 中定义函数,可以多种参数组合使用。但是,参数定义顺序必须是:位置参数、默认参数、动态参数。

函数做参数

函数就相当于是一个变量,同时也可被哈希,所以也可将函数作为参数,传入到函数之中。

匿名函数

基于 lambda 表达式实现定义一个没有名字的函数,格式为:lambda 参数: 函数体

匿名函数支持任意参数,但只能支持单行的代码。所以,匿名函数只能处理非常简单的功能。

func = lambda x: x + 100
value = func(10)
print(value)  # 结果为:110

内置函数

callable()

是否可在后面加括号执行,函数、类、具有 call 方法的对象都是可执行的。

def func():
    pass

print(callable(func))  # 结果为:True

exec()

函数 exec 将字符串作为代码执行。

s = "print('hello, world')"
exec(s)  # hello, world

在大多数情况下,还应添加第二个参数,用作代码字符串的命名空间;否则代码将污染你的命名空间,即修改你的变量。

exec("print = 1")
print('666')  # 报错

通过 exec 执行赋值语句创建的变量位于 scope 中:

scope = {}
exec("print = 1", scope)
print("666")

eval()

计算用字符串表示的 Python 表达式的值,并返回结果:

a = eval(input("请输入:"))  # 假设输入:1 + 2 * 3
print(a)  # 7

与 exec 一样,也可向 eval 提供一个命名空间。

scope = {}
scope["x"] = 2
scope["y"] = 4
print(eval("x * y", scope))  # 8

type()

获取一个对象的类型。

s = "李小龙"
print(type(s))  # <class 'str'>

filter()

用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。

该函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。

a = [1, 2, 3, 4, 5]
b = filter(lambda x: x > 2, a)
print(list(b))  # [3, 4, 5]

map()

根据提供的函数对指定序列做映射。

a = [1, 2, 3]
b = map(lambda x: x > 2, a)
print(list(b))  # [False, False, True]

reduce()

对参数序列中元素进行累积。

from functools import reduce

a = reduce(lambda x, y: x + y, [1, 2, 3], 10)
print(a)  # 16

zip()

p 将两个序列“缝合”起来,并返回一个由元组组成的序列。

names = ['李小龙', '李中龙', '李大龙']
ages = [10, 15, 18]
s = zip(names, ages)
for name, age in s:
    print(name, 'is', age, 'years old')

当序列长度不同时,函数 zip 将在最短的序列用完后停止“缝合”。

enumerate()

函数 enumerate 能够迭代索引 - 值对:

lst = ['Python', 'Java', 'C']
for index, string in enumerate(lst):
    if 'Python' in string:
        lst[index] = '666'
print(lst)  # ['666', 'Java', 'C']

函数特殊用法

  • 函数名 + ():执行函数
  • 函数名.__name__:获取函数的名称,其实是个字符串
  • 函数名.__doc__:获取函数的注释
    def func():
      """我是 func 函数"""
      print(666)
    
    func()  # 666
    print(func.__name__)  # func
    print(func.__doc__)  # 我是 func 函数

闭包

在一个外函数中定义了一个内函数,内函数里用到了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成了一个闭包。

一般情况下,如果一个函数结束,函数内部的所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

def outer(arg):
    def inner():
        print(arg)  # 在内函数中用到了外函数的临时变量
    return inner  # 外函数的返回值是内函数的引用

func = outer(666)  # 内函数的引用返回给了 func
func()  # 执行 inner 函数,结果为:666

计数器

def counter(first=0):
    def add_one():
        nonlocal first
        first += 1
        print(first)
    return add_one

num = counter()
num()  # 1
num()  # 2
num()  # 3

需要使用 nonlocal 关键字修饰外部函数的变量,才可在内部函数中修改它。

柯里化

指将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数,如 z =f(x,y)转换成 z =f(x)(y)的形式。

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

print((add(1, 2)))  # 3

def plus(x):
    def fn(y):
        return x + y

    return fn

print(plus(2)(3))  # 5

原函数调用为 add(1, 2),柯里化目标为 plus(2)(3)。

装饰器

装饰器其实是一种闭包,在不修改原函数内容的前提下,通过 @函数(装饰器的语法糖写法)可以实现在函数前后自定义执行一些功能(批量操作会更有意义)。

装饰器可以简单理解为,用来装饰其他函数的,即为其他函数添加特定功能的函数,实际上是将原函数更改为其他函数,然后在此函数中再去调用原函数。装饰器函数两个基本原则:

  • 装饰器不能修改被装饰函数的源码
  • 装饰器不能修改被装饰函数的调用方式
def outer(origin):
    def inner(*args, **kwargs):
        print("before")
        res = origin(*args, **kwargs)  # 调用原来的 func 函数
        print("after")
        return res
    return inner

@outer  # func = outer(func)
def func(a1, a2):
    print("我是 func 函数")
    value = (11, 22, 33)
    return value

value = func(11, a2=22)
print(value)

输出结果如下:

before
我是 func 函数
after
(11, 22, 33)

多个装饰器的装饰过程:离函数最近的装饰器先装饰,然后外面的装饰器再进行装饰,由内到外的装饰过程。

计时器

import time

def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('运行时间是 %s 秒' % (stop_time - start_time))
    return wrapper

@timmer
def i_can_sleep():
    time.sleep(3)

i_can_sleep()

带有参数的装饰器

def new_tips(argv):
    def tips(fn):
        def inner(a, b):
            print("start %s" % argv)
            fn(a, b)
            print("stop\n")
        return inner
    return tips

@new_tips("add")
def add(a, b):
    print(a, "+", b, "=", a + b)

@new_tips("sub")
def sub(a, b):
    print(a, "-", b, "=", a - b)

add(1, 2)
sub(1, 2)

类装饰器

想要让类的实例对象能够像函数一样进行调用,需要在类里面使用 call 方法,把类的实例变成可调用对象,类装饰器装饰函数功能在 cal 方法里面进行添加。

class Check:
    def __init__(self, fn):
        self.__fn = fn

    def __call__(self, *args, **kwargs):
        print("登陆")
        self.__fn(*args, **kwargs)

@Check
def comment():
    print("发表评论")

comment()

迭代器

lst = [1, 2, 3]
it = iter(lst)
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3

生成器

生成器是由函数 +yield 关键字创造出来的写法,在特定情况下,用他可以节省内存。当函数中有 yield 存在时,这个函数就叫生成器函数。

def func():
    print(666)
    yield 123

f = func()
print(f)  # 结果为:<generator object func at 0x00000>

执行生成器函数时,函数体默认不会被执行,返回一个生成器对象。

def func():
    print(666)
    yield 123  # 有点像 return,执行到这个位置就不再执行
    print(777)
    yield 456
    print(888)

v = func()
n1 = next(v)  # next 里面放生成器对象,进入生成器函数并执行
print(n1)

输出结果如下:

666
123
n2 = next(v)  # 从上次 yield 返回位置继续向下执行
print(n2)

输出结果如下:

777
456
n3 = next(v)  # 从上次 yield 返回位置继续向下执行
print(n3)

这时没有 yield 了,默认return None,程序会报错:生成器中的代码执行完毕了。

自定义 range 函数

def frange(start, stop, step):
    x = start
    while x < stop:
        yield x
        x += step

for i in frange(1, 10, 0.5):
    print(i)

项目开发

def func():
    print(666)
    yield 123
    print(777)
    yield 456

data = func()
for item in data:
    print(item)  # 本质是 next(data)

正文完
 0
阿伯手记
版权声明:本站原创文章,由 阿伯手记 于2024-01-23发表,共计5909字。
转载说明:本站原创内容,除特殊说明外,均基于 CC BY-NC-SA 4.0 协议发布,转载须注明出处与链接。
评论(没有评论)
验证码

阿伯手记

阿伯手记
阿伯手记
喜欢编程,头发渐稀;成长路上,宝藏满地
文章数
766
评论数
204
阅读量
450373
今日一言
-「
热门文章
职场救急!AI请假话术生成器:1秒定制高通过率理由

职场救急!AI请假话术生成器:1秒定制高通过率理由

超级借口 不好开口?借口交给我!智能生成工作请假、上学请假、饭局爽约、约会拒绝、邀约推辞、万能借口等各种借口理...
夸克网盘快传助手提高非VIP下载速度

夸克网盘快传助手提高非VIP下载速度

夸克网盘限速这个大家都知道,不开会员差不多限速在几百 K。那有没有办法在合法合规途径加速下载夸克网盘呢?这里推...
国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

本文收集了目前国内已部署 DeepSeek 模型的第三方列表,个个都是免费不限次数的满血版 DeepSeek,...
巴别英语:用美剧和TED演讲轻松提升英语听力与口语

巴别英语:用美剧和TED演讲轻松提升英语听力与口语

还在为枯燥的英语学习而烦恼吗?巴别英语通过创新的美剧学习模式,让英语学习变得生动有趣。平台提供海量美剧和 TE...
Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 是一款在线中文姓名生成器,可在几秒内生成符合个人需求的中文名字。...
TVAPP:开源电视盒子资源库,一键打造家庭影院

TVAPP:开源电视盒子资源库,一键打造家庭影院

导语 TVAPP 是一个专为 Android TV 电视盒子用户打造的开源影音资源库,集成了影视、直播、游戏等...
2025年12月 每日精选

2025年12月 每日精选

关于每日精选栏目 发现一些不错的资源,点击 这里 快速投稿。 12 月 26 日 .ax 顶级域 目前全球唯一...
最新评论
15220202929 15220202929 怎么用
八对 八对 麻烦大佬更新下【堆新】的友链站名:八对星星描述:极目星视穹苍无界•足履行者大地有疆链接:https://8dui.com图标:https://cf.8dui.com/logo.webp横标:https://cf.8dui.com/logo-w.webp订阅:https://8dui.com/rss.xml
三毛笔记 三毛笔记 已添加
DUINEW DUINEW 已添加贵站,期待贵站友链~博客名称:堆新博客地址:https://duinew.com/博客描述:堆新堆新,引力向新!——堆新(DUINEW)博客头像:https://d.duinew.com/logo.webp横版头像:https://d.duinew.com/logo-w.webp博客订阅:https://duinew.com/rss.xml
hedp hedp 没看懂
bingo bingo 直接生成就可以啦,也可以添加一些选项
满心 满心 申请更新下友联信息,原名:满心记,现名:周天记原域名:qq.mba,现域名:zhoutian.com描述:我在人间混日子
开业吉日 开业吉日 没看明白这个怎么用
开业吉日 开业吉日 beddystories 这个网站太赞了,收藏
热评文章
夸克网盘快传助手提高非VIP下载速度

夸克网盘快传助手提高非VIP下载速度

夸克网盘限速这个大家都知道,不开会员差不多限速在几百 K。那有没有办法在合法合规途径加速下载夸克网盘呢?这里推...
清华大学官方免费DeepSeek教程

清华大学官方免费DeepSeek教程

AI 领域近期最引人注目的焦点当属 DeepSeek,这款由中国创新企业深度求索研发的人工智能工具,正以开放源...
Short-Link 免费开源短网址程序,基于Fastify、Vercel和Supabase构建

Short-Link 免费开源短网址程序,基于Fastify、Vercel和Supabase构建

Short-Link 是一款基于 Fastify、Vercel 和 Supabase 构建的 URL 缩短服务...
国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

国内已部署DeepSeek模型第三方列表 免费满血版联网搜索

本文收集了目前国内已部署 DeepSeek 模型的第三方列表,个个都是免费不限次数的满血版 DeepSeek,...
Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 在线中文姓名生成器

Chinese Name Generator 是一款在线中文姓名生成器,可在几秒内生成符合个人需求的中文名字。...
BeddyStories 完全免费儿童睡前故事库,让孩子随时随地入睡更轻松

BeddyStories 完全免费儿童睡前故事库,让孩子随时随地入睡更轻松

BeddyStories 是一个致力于为儿童提供优质睡前故事的在线平台,用户可以在这里找到来自世界各地的经典故...
DrawLink:一键生成链接视觉卡片,提升分享点击率

DrawLink:一键生成链接视觉卡片,提升分享点击率

小贴士 :此站或已变迁,但探索不止步。我们已为您备好「类似网站」精选合集,相信其中的发现同样能为您带来惊喜。