Python 函数定义详解(More on Defining Functions)- 默认参数/位置参数/关键字参数

news2024/12/23 8:35:10

在这里插入图片描述

1.函数的定义和调用方法

1.1函数定义方法

"""
    def 关键字用来定义一个函数。
    function_name 是函数名,应遵循命名规范。
    parameter1, parameter2, ... 是函数的参数列表,可以是任意数量和类型的参数。
    函数体是用缩进(通常为4个空格)来表示的代码块。
    return 语句用于返回函数的结果。
"""
# def function_name(parameter1, parameter2, ...):
    # Function body
    #    return result

1.2函数调用方法

"""
function_name 是要调用的函数名。
argument1, argument2, ... 是传递给函数的参数列表。
函数执行后,将返回一个结果,可以将其赋值给一个变量。
"""
# result = function_name(argument1, argument2, ...)

1.3示例:定义一个函数计算两个数之和

"""
    定义个函数计算两个数之和
"""
def add_numbers(num1,num2):# 定义函数
    result = num1 +num2
    return result

sum = add_numbers(100,200)# 调用函数

print(sum) # 输出结果为300

2.默认值参数(Default Argument Values)

  Python允许在函数定义中为参数提供默认值,这使得函数在调用时可以省略部分参数,从而提供了更大的灵活性。

2.1示例1:简单的示例函数,用于打招呼

def greet(name, greeting="Hello"):
    # 参数name是位置参数,必须提供值。
    # 参数greeting是默认值参数,如果不提供值,默认为"Hello"。
    return f"{greeting}, {name}!"

# 调用函数时可以只提供name参数,greeting参数会使用默认值。
result1 = greet("Alice")
print(result1)  # 输出 "Hello, Alice!"

# 也可以同时提供name和greeting参数的值,这将覆盖默认值。
result2 = greet("Bob", "Hi")
print(result2)  # 输出 "Hi, Bob!"

  greet函数接受两个参数,namegreeting,其中greeting是一个带有默认值的参数,默认值为"Hello"。当调用函数时,如果只提供了name参数,那么greeting参数将使用默认值。如果同时提供了name和greeting的值,那么提供的值将覆盖默认值。

2.2python官网示例

def ask_ok(prompt, retries=4, reminder='Please try again!'):
    # 定义一个函数ask_ok,接受三个参数:prompt、retries和reminder。
    # 默认情况下,retries被设置为4,reminder被设置为'Please try again!'。
    
    while True:
        # 进入一个无限循环,直到用户提供有效的回答或达到重试次数。
        
        ok = input(prompt)
        # 使用input()函数向用户提供一个提示,等待用户的输入,并将输入保存在ok变量中。
        
        if ok in ('y', 'ye', 'yes'):
            return True
            # 如果用户输入了'y', 'ye', 'yes'中的一个,函数返回True。
            
        if ok in ('n', 'no', 'nop', 'nope'):
            return False
            # 如果用户输入了'n', 'no', 'nop', 'nope'中的一个,函数返回False。
            
        retries = retries - 1
        # 如果用户输入既不是True也不是False,减少重试次数retries。
        
        if retries < 0:
            raise ValueError('invalid user response')
            # 如果重试次数小于0,引发一个ValueError异常,表示用户提供的回答无效。
            
        print(reminder)
        # 如果用户提供的回答不在有效选项内,打印提醒消息reminder,然后继续循环。

# 通过以下方式调用:
ask_ok('Do you really want to quit?')#只给出必选实参
ask_ok('OK to overwrite the file?', 2)#给出一个可选实参
ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')#给出所有实参

2.3重要提示

  默认值只计算一次。默认值为列表、字典或类实例等可变对象时,会产生与该规则不同的结果。
  下面以列表、字典或类实例示例说明:

"""
    列表作为默认参数
    在这个例子中,期望每次调用append_to函数时,列表都是新的,互不干扰。
    然而,由于默认参数的特性,得到的列表是共享的,所以每次调用都会影响这个列表。
"""
def append_to(num, target=[]):  
    target.append(num)  
    return target  
  
print(append_to(1))  # 输出:[1]  
print(append_to(2))  # 输出:[1, 2],而不是[1]  
print(append_to(3))  # 输出:[1, 2, 3],而不是[1, 2]
"""
    字典作为默认参数
    期望每次调用update_dict函数时,字典都是新的,但是因为默认参数的特性,得到的字典是共享的。
"""
def update_dict(key, target={}):  
    target[key] = key  
    return target  
  
print(update_dict(1))  # 输出:{1: 1}  
print(update_dict(2))  # 输出:{1: 1, 2: 2},而不是{1: 1}  
print(update_dict(3))  # 输出:{1: 1, 2: 2, 3: 3},而不是{1: 1, 2: 2}
"""
    类实例作为默认参数
    期望每次调用increment_by函数时,TestClass的实例都是新的,互不干扰。然而,由于默认参数的特性,得到的实例是共享的,所以每次调用都会影响这个实例的状态
"""
class TestClass:  
    def __init__(self):  
        self.value = 0  
  
    def increment(self, num):  
        self.value += num  
        return self.value  
  
def increment_by(num, target=TestClass()):  
    target.increment(num)  
    return target.value  
  
print(increment_by(1))  # 输出:1  
print(increment_by(2))  # 输出:3,而不是2  
print(increment_by(3))  # 输出:6,而不是5

2.4建议

  1.使用可变对象作为默认参数时,可以考虑使用None作为默认值,并在函数内部进行判断和处理。每次调用的时候,都会创建一个新的列表,避免了共享默认参数的问题。

def append_to(num, target=None):  
    if target is None:  
        target = []  
    target.append(num)  
    return target
    
print(append_to(1))
print(append_to(2))
print(append_to(3))

  2.对于字典或类实例等可变对象,可以考虑使用函数内部的局部变量作为默认值,而不是使用一个全局变量。每次调用的时候都会创建一个新的字典或实例,避免共享默认参数的问题。

def update_dict(key, target=None):  
    if target is None:  
        target = {}  
    target[key] = key  
    return target
def increment_by(num, target=None):  
    if target is None:  
        target = TestClass()  
    target.increment(num)  
    return target.value

  3.如果可能的话,尽量避免使用可变对象作为默认参数,可以避免潜在的共享问题。考虑使用不可变对象(如字符串、数字或元组)作为默认参数。
  4.如果默认参数的值是一个复杂对象(如列表、字典或类实例),并且需要重复使用,可以考虑将该对象定义为全局变量或属性,并在函数内部引用该全局变量。可以确保每次调用函数时都使用同一个对象,避免了重复创建对象的开销。但是需要注意避免全局变量导致的命名冲突和其他问题。
  5.如果默认参数的值是一个不可变对象(如字符串、数字或元组),并且需要重复使用,可以考虑将该对象定义为函数的一个属性或静态变量。这样可以避免每次调用函数时都重新计算该对象的开销。但是需要注意避免该对象被修改导致的问题。

3.关键字参数(Keyword Arguments

  kwarg=value形式的关键字参数 也可以用于调用函数。
  在函数调用中前面带有标识符(例如 arg=)或者作为包含在前面带有**的字典里的值传入。
  如:3和5在以下对complex()方法的调用中均属于关键字参数
  complex(real=3, imag=5)
  complex(**{'real': 3, 'imag': 5})

3.1官网示例

"""
    parrot()函数接受一个必选参数(voltage)和三个可选参数(state, action 和 type)
    其中voltage既可以是位置参数,也可以是关键字参数;
    state、action、type是关键字参数
"""
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print("-- This parrot wouldn't", action, end=' ')
    print("if you put", voltage, "volts through it.")
    print("-- Lovely plumage, the", type)
    print("-- It's", state, "!")

# 可用下列方法进行调用
parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

# 以下调用函数的方式均无效
parrot()                     # required argument missing
parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
parrot(110, voltage=220)     # duplicate value for the same argument
parrot(actor='John Cleese')  # unknown keyword argument

  函数调用时,关键字参数必须跟在位置参数后面。所有传递的关键字参数都必须匹配一个函数接受的参数(比如,actor不是函数 parrot 的有效参数),关键字参数的顺序并不重要。这也包括必选参数,(比如,parrot(voltage=1000) 也有效)。不能对同一个参数多次赋值。

3.2 ```*args和**kwargs

  在Python中,*args **kwargs 是特殊的参数,用于在函数定义中接收任意数量的位置参数和关键字参数。
  *args表示一个元组类型的参数,用于接收任意数量的位置参数。这些参数将按照它们在函数调用中的顺序依次赋值给*args参数。在函数体中,可以像处理普通元组一样处理*args参数。
  **kwargs表示一个字典类型的参数,用于接收任意数量的关键字参数。这些参数将作为字典的键值对赋值给 **kwargs参数。在函数体中,可以使用**kwargs参数来访问这些关键字参数。

"""
    *argument 形参接收一个元组,在它之前的为位置参数
    **keywords 形参接收一个字典,传参数数时必须带变量名
"""
def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I'm sorry, we're all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    for kw in keywords:
        print(kw, ":", keywords[kw])

#调用该函数
cheeseshop("Limburger", "It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           shopkeeper="Michael Palin",
           client="John Cleese",
           sketch="Cheese Shop Sketch")

# 输出结果:
"""
    -- Do you have any Limburger ?
    -- I'm sorry, we're all out of Limburger
    It's very runny, sir.
    It's really very, VERY runny, sir.
    ----------------------------------------
    shopkeeper : Michael Palin
    client : John Cleese
    sketch : Cheese Shop Sketch
"""

4.特殊参数

  默认情况下,参数可以按位置或显式关键字传递给Python 函数。为了让代码易读、高效,最好限制参数的传递方式,这样,开发者只需查看函数定义,即可确定参数项是仅按位置、按位置或关键字,还是仅按关键字传递。
函数定义如下:
在这里插入图片描述

  / * 是可选的。这些符号表明形参如何把参数值传递给函数:位置位置或关键字关键字

4.1 位置或关键字参数

  函数定义中未使用/ * 时,参数可以按位置或关键字传递给函数。

4.2 仅位置参数

  仅限位置时,形参的顺序很重要,且这些形参不能用关键字传递。仅限位置形参应放在/ (正斜杠)前。/ 用于在逻辑上分割仅限位置形参与其它形参。如果函数定义中没有 /,则表示没有仅限位置形参。
/ 后可以是 位置或关键字 或 仅限关键字 形参。

4.3 仅限关键字参数

  把形参标记为 仅限关键字,表明必须以关键字参数形式传递该形参,应在参数列表中第一个 仅限关键字形参前添加*

"""
    / 和 * 在参数中使用的语法:
    def function(positional_or_keyword_parameters, *, keyword_only_parameters):
    def function(positional_only_parameters, /, positional_or_keyword_parameters,*, keyword_only_parameters):
    
    在“/”左边的参数被视为仅位置参数
    如果函数定义中“/”没有指定,则函数中所有参数都不是仅位置参数
    仅位置参数的可选值的逻辑与位置-关键字参数的逻辑相同。
    一旦使用默认值指定了仅位置参数,下面的仅位置参数和位置-关键字参数也需要具有默认值。
"""
# 有效的函数定义:
def fun1(positional1, positional2, /, positional_or_keyword, *, keywords):pass
def fun2(positional1, positional2=None, /, positional_or_keyword=None, *, keywords):pass
def fun3(positional1, positional2=None, /, *, keywords):pass
def fun4(positional1, positional2=None, /):pass
def fun5(positional1, positional2, /, positional_or_keyword):pass
def fun6(positional1, positional2, /):pass
def fun7(positional_or_keyword, *, keywords):pass
def fun8(*, keywords):pass

# 无效定义
def fun9(positional1, positional2=None, /, positional_or_keyword, *, keywords):pass
def fun10(positional1=None, positional2, /, positional_or_keyword=None, *, keywords):pass
def fun11(positional1=None, positional2, /):pass

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1191863.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线上SQL超时场景分析-MySQL超时之间隙锁 | 京东物流技术团队

前言 之前遇到过一个由MySQL间隙锁引发线上sql执行超时的场景&#xff0c;记录一下。 背景说明 分布式事务消息表&#xff1a;业务上使用消息表的方式&#xff0c;依赖本地事务&#xff0c;实现了一套分布式事务方案 消息表名&#xff1a;mq_messages 数据量&#xff1a;3…

Facebook广告被暂停是什么原因?Facebook广告账号被封怎么办?

许多做海外广告投放的小伙伴经常遇到一个难题&#xff0c;那就是投放的Facebook广告被拒或 Facebook 广告帐户被关闭赞停的经历&#xff0c;随之而来的更可能是广告账户被封&#xff0c;导致资金的损失。本文将从我自身经验&#xff0c;为大家分享&#xff0c;Facebook广告被暂…

kafka 集群企业部署最佳实践

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

Git安装配置保姆级教程和Git创建仓库的基本原理和常用命令

目录 前言 一、Git简介 1.Git 与 SVN 区别点 2.Git的介绍 3.Git 工作流程 4.Git 工作区、暂存区和版本库 二、Git安装配置 1.Linux 平台上安装 2.Windows 平台上安装 三、Git 创建仓库和下载 1、首先需要注册一个gitee账号 2.git初始化并提交到远程仓库 3.另一用户…

chrome 的vue3的开发者devtool不起作用

问题&#xff1a; 刚刚vue2升级到vue3&#xff0c;旧的devtool识别不了vue3数据。 原因&#xff1a; devtool版本过低。升级到最新。 解决&#xff1a; 去github下载vuetool项目代码&#xff1a; GitHub - vuejs/devtools: ⚙️ Browser devtools extension for debugging…

Linux学习笔记之五(父子进程、孤儿进程、僵尸进程、守护进程)

Linux 1、进程1.1、进程的六种状态1.2、创建子进程1.3、添加子进程任务1.4、孤儿进程、僵尸进程、守护进程1.4.1、避免僵尸进程1.4.2、创建守护进程1.4.3、杀死守护进程 1.5、综合练习 1、进程 进程可以简单的理解为一个正在执行的程序&#xff0c;它是计算机系统中拥有资源和…

django建站过程(4)创建文档显示页面

django建站过程&#xff08;4&#xff09;创建文档显示页面 创建文档显示页面项目主文件夹schoolapps中的文件urls.py在APP“baseapps”中创建url.py文件编写视图模板继承bootstrap创建head.html创建doclist.html创建docdetail.html 使用 markdown 编辑器安装模块Model 模型的d…

Hello World背后的逻辑

一门语言的开发入门&#xff0c;总是抬手就能整出一个「Hello World Demo」。比如下面这样&#xff1a; 显然&#xff0c;熟悉 iOS 开发的同学都知道&#xff0c;上面这个来自 Objective-C。 今天&#xff0c;我们就从这熟悉的代码入手&#xff0c;来一起研究研究「Hello Worl…

泄露35TB数据,医疗巨头Henry Schein遭受黑猫勒索组织攻击

近日&#xff0c;据Bleeping Computer 网站消息&#xff0c;BlackCat&#xff08;黑猫&#xff09;勒索软件团伙将医疗保健巨头Henry Schein 添加到了其暗网泄露网站&#xff0c;并声称其破坏了该公司的网络&#xff0c;窃取了35 TB的敏感文件&#xff0c;这些文件包括了Henry …

BES 在大规模向量数据库场景的探索和实践

导读 本文整理自 2023 年 9 月 5 日 QCon 全球软件开发大会 2023 北京站 —— 向量数据库分论坛的同名主题演讲《BES 在大规模向量数据库场景的探索和实践》。 全文5989字&#xff0c;预计阅读时间15分钟。 向量数据库是一种专门用于存储和查询向量数据的数据库系统。通过 Emb…

verdi如何打开时可以加载配置比如字体

打开tcl使能 找到配置字体的命令 其实其他有需要的文件配置都可以在这里找到对应的指令 存储文件 新建verdi001.tcl文件 输入想要调整的字体以及大小 verdiSetFont -font "Bitstream Vera Sans" -size "18" verdiSetFont -monoFont "Courier&q…

【 云原生 | K8S 】kubectl 详解

目录 1 kubectl 2 基本信息查看 2.1 查看 master 节点状态 2.2 查看命名空间 2.3 查看default命名空间的所有资源 2.4 创建命名空间app 2.5 删除命名空间app 2.6 在命名空间kube-public 创建副本控制器&#xff08;deployment&#xff09;来启动Pod&#xff08;nginx-wl…

做哪些副业可以日赚一百?对程序员来说简直不要太容易!

日赚一百&#xff1f;对程序员来说简直不要太容易&#xff01;下面给程序员们推荐一些日赚100的副业&#xff1a; ①外包接单 程序员简单粗暴赚钱的副业之一。 外包接单的类型包括但不限于&#xff1a;软件开发、硬件开发、小程序功能开发、web开发……大到一个系统的开发、…

什么样的CRM系统更适合外贸企业?

外贸CRM系统作为外贸客户关系管理的工具&#xff0c;已经成为了当下外贸企业对外贸易过程中不可或缺的一环。那什么样的CRM系统更适合外贸企业&#xff1f;小Z向您推荐Zoho CRM。下面说说它到底有什么好处和作用。 一、搭建更高效的客户关系管理系统 外贸企业从前期推广、开发…

202205(第13届)蓝桥杯Scratch图形化编程青少组(国赛_中级)真题

202205(第13届)蓝桥杯Scratch图形化编程青少组(国赛_中级)真题 第 1 题 以下程序&#xff0c;小猫在移动完成后不能回到初始位置的是&#xff1f;&#xff08; &#xff09; A&#xff1a; B&#xff1a; C&#xff1a; D&#xff1a; 第 2 题 以下程序&#xff0c;询问…

SAP 10策略测试及简介

从今天开始将把PP模块中常用的一些策略进行一个测试,编写成系统的文档,有点策略经常不用自己都忘了一些策略的特性。所以还是有必须形成文档的形式记录下来 1、首先准备好物料 成品物料为AB0,在MRP3视图中维护对应的策略组的10 同时选择消耗模式为2.消耗期间都是999 2、其他…

环境变量小结

一 常见环境变量介绍 1 PATH 到了现在&#xff0c;我们也知道我们轻轻敲下ls指令&#xff0c;其实会转为一个可执行文件在运行&#xff0c;也就变成了一个进程&#xff0c;所以ls是让文件运行&#xff0c;./test也是让文件运行&#xff0c;凭什么我们的可执行文件就要加个./(这…

IDEA调试总结

前言 由于 IDEA 每个人使用的版本不同以及快捷键的设置不同&#xff0c;所以忽略了快捷键的使用。如果不知道快捷键请在 IDEA 工具栏里面点开 Run 菜单即可知悉 图标介绍 下面咱们进入看图说话环节&#xff0c;下列图标小伙伴知道是啥功能么&#xff1f;日常开发进行 Debug 使…

Spring-Security前后端分离权限认证

前后端分离 一般来说&#xff0c;我们用SpringSecurity默认的话是前后端整在一起的&#xff0c;比如thymeleaf或者Freemarker&#xff0c;SpringSecurity还自带login登录页,还让你配置登出页,错误页。 但是现在前后端分离才是正道&#xff0c;前后端分离的话&#xff0c;那就…

React状态管理方案盘点

您好&#xff0c; 如果喜欢我的文章或者想上岸大厂&#xff0c;可以关注公众号「量子前端」&#xff0c;将不定期关注推送前端好文、分享就业资料秘籍&#xff0c;也希望有机会一对一帮助你实现梦想 前言 本文不会介绍各个状态管理工具的具体使用或者如何二次封装&#xff0c…