Python中的函数定义中的斜杠/和星号*
Python中的函数定义中的斜杠/和星号*
示例
看一段代码
def say_hello(name,age=18):
print(f'你好!我是{name},今年我{age}啦。')
say_hello('老吴')
say_hello(name='小钱')
# 输出
你好!我是老吴,今年我18啦。
你好!我是小钱,今年我18啦。这个代码你学过python不可能不懂,name是形式参数,也叫位置参数,我们一样可以用参数名=的方式传递(关键字参数)
再看一段代码:这是list列表的index方法的定义描述
>>> help(list.index)
Help on method_descriptor:
index(self, value, start=0, stop=9223372036854775807, /)
Return first index of value.
Raises ValueError if the value is not present.我们跟上面一样做个简单的测试
>>> list1=[2,3,4]
>>> list1.index(2)
0
>>> list1.index(value=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list.index() takes no keyword arguments提示说list.index没有关键字参数
细心的同学应该发现了,两者的差异在于第二个函数index的定义最后有个/,这个在初学的时候我们一般不会怎么接触到。但其实非常有用。
除了/,还有一个*号,也会出现在函数定义中(注意不是*args和**kwargs)
比如list的sort方法
>>> help(list.sort)
Help on method_descriptor:
sort(self, /, *, key=None, reverse=False)
Sort the list in ascending order and return None.>>> list1=[3,2,4]
>>> list1.sort(reverse=True) # 关键字参数传递方式
>>> list1
[4, 3, 2]
>>> list1.sort(None,reverse=True) # 不能用位置参数
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sort() takes no positional arguments
斜杠/之前必须是位置参数
这个特性是在python3.8中发布的,仅限位置形参。
https://docs.python.org/zh-cn/3.8/whatsnew/3.8.html
示例1: 对之前的say_hello函数加个/看看
def say_hello(name,/,age=18):
print(f'你好!我是{name},今年我{age}啦。')
say_hello('老吴')
say_hello(name='小钱')
你好!我是老吴,今年我18啦。
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-11-e09734cd0de5> in <module>
2 print(f'你好!我是{name},今年我{age}啦。')
3 say_hello('老吴')
----> 4 say_hello(name='小钱')
TypeError: say_hello() got some positional-only arguments passed as keyword arguments: 'name'非常清楚的提示了,say_hello函数给一个仅限位置参数name用了关键字传参的方式
示例2:放到最后会怎样?
def say_hello(name,age=18,/):
print(f'你好!我是{name},今年我{age}啦。')
say_hello('老吴',19)
say_hello('小钱',age=19)
# 输出如下
你好!我是老吴,今年我19啦。
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-14-911127531c6c> in <module>
2 print(f'你好!我是{name},今年我{age}啦。')
3 say_hello('老吴',19)
----> 4 say_hello('小钱',age=19)
TypeError: say_hello() got some positional-only arguments passed as keyword arguments: 'age'对于默认值参数age,一样的不能用关键字参数方式传递,只能用位置参数
示例3:/放在中间,对于/后的是没有限制的,下面2个调用都ok的。
def say_hello(name,/,age):
print(f'你好!我是{name},今年我{age}啦。')
say_hello('老吴',18)
say_hello('小钱',age=18)
比如len
>>> help(len)
Help on built-in function len in module builtins: len(obj, /)
Return the number of items in a container.你从来不会这样调用,你都不知道有obj这个参数,但其实你应该明白它是有参数的。
>>> len(obj='ab')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: len() takes no keyword arguments
星号*后面必须是关键字参数
没有找到出处
但有了/的基础,你看到这个要求就比较容易理解了。
示例1:
def say_hello(name,*,age):
print(f'你好!我是{name},今年我{age}啦。')
say_hello('小钱',age=18) # * 号后面是关键字参数
say_hello(name='啊徐',age=18) # * 前面的你随便用什么方式都可以(如果没有/的话)
say_hello('老吴',18) # 你不能用位置参数的方式来调用 # 输出
你好!我是小钱,今年我18啦。
你好!我是啊徐,今年我18啦。
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-21-2a30cd8f06c0> in <module>
3 say_hello('小钱',age=18)
4 say_hello(name='啊徐',age=18)
----> 5 say_hello('老吴',18) TypeError: say_hello() takes 1 positional argument but 2 were given
混合
官方的定义:https://peps.python.org/pep-0570/
def func(positional_only_parameters, /, positional_or_keyword_parameters,
*, keyword_only_parameters):
pass混合后有些定义跟普通的函数定义方式略有调整。
# 对的
def func1(p1, p2, /, p_or_kw, *, kw):
pass
def func2(p1, p2=None, /, p_or_kw=None, *, kw):
pass
def func3(p1, p2=None, /, *, kw): # 这个可能是最容易 让人误判的
pass
def func4(p1, p2=None, /):
pass
def func5(p1, p2, /, p_or_kw):
pass
def func6(p1, p2, /):
pass
def func7(p_or_kw, *, kw):
pass
def func8(*, kw):
pass以上都是合法的,以下就是不合法的
# 错的
def fun9(p1, p2=None, /, p_or_kw, *, kw): # 错在 p_or_kw
pass
def fun10(p1=None, p2, /, p_or_kw=None, *, kw): # 错在 p1和 p2,
pass
def fun11(p1=None, p2, /):
pass
好处?用途?
这么做的好处是啥呢?
将形参标记为仅限位置形参将允许在未来修改形参名而不会破坏客户的代码。
示例1
def say_hello(name,/,age=18):
print(f'你好!我是{name},今年我{age}啦。') say_hello('wu',18) #通常你会这样调用
# 以后,你觉得name不合适,改为xingming
def say_hello(xingming,/,age=18):
print(f'你好!我是{xingming},今年我{age}啦。') say_hello('wu',18) # 你的调用仍然可以正常工作
示例2:来看一个函数定义
def foo(name, **kwds):
print(f'My name is : {name} ')
return 'name' in kwds foo('wuxianfeng',name='zhangsan') # 本意是输出用户名,看看是否提供关键字参数nameTypeError Traceback (most recent call last)
<ipython-input-33-07a88704ecfd> in <module>
4
5
----> 6 foo('wuxianfeng',name='zhangsan') TypeError: foo() got multiple values for argument 'name'这样改下即可。此name非彼name,name好像可以使用两次
def foo(name, /,**kwds):
print(f'My name is : {name} ')
return 'name' in kwds foo('wuxianfeng',name='zhangsan')
Python中的函数定义中的斜杠/和星号*的更多相关文章
- [Python]Python Class 中的 函数定义中的 self
In [80]: class MyClass001: ....: def selfDemo(self): ....: print 'My Demo' ....: In [81]: p = MyClas ...
- python开发_python中的函数定义
下面是我做的几个用列: #python中的函数定义,使用和传参 def_str = '''\ python中的函数以如下形式声明: def 函数名称([参数1,参数2,参数3......]): 执行语 ...
- python 可变参数函数定义* args和**kwargs的用法
python函数可变参数 (Variable Argument) 的方法:使用*args和**kwargs语法.其中,*args是可变的positional arguments列表,**kwargs是 ...
- python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程
python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...
- 第7.23节 Python使用property函数定义属性简化属性访问的代码实现
第7.23节 Python使用property函数定义属性简化属性访问的代码实现 一. 背景 在本章前面章节中,我们介绍了类相关的知识,并举例进行了说明,在这些例子中会定义一些形如 ...
- Python使用property函数定义的属性名与其他实例变量重名会怎么样?
首先如果定义的属性名与该属性对应的操作方法操作的实例对象同名就会触发无穷的递归调用,相关部分请参考<Python案例详解:使用property函数定义与实例变量同名的属性会怎样?> 但如果 ...
- Python使用property函数定义属性访问方法如果不定义fget会怎么样?
我们知道Python使用property函数定义属性访问方法时的语法如下: 实例属性=property(fget=None, fset=None, fdel=None, doc=None) 而是要@p ...
- python简单的函数定义和用法实例
python简单的函数定义和用法实例 这篇文章主要介绍了python简单的函数定义和用法,实例分析了Python自定义函数及其使用方法,具有一定参考借鉴价值,需要的朋友可以参考下 具体分析如下: 这里 ...
- python中的函数(定义、多个返回值、默认参数、参数组)
函数定义 在python中函数的定义以及调用如下代码所示: def test(x): y = x+1 return y result = test(2) print(result) 多个返回值的情况 ...
- python的函数定义中99%的人会遇到的一个坑
列表是一种经常使用的数据类型.在函数的定义中,常常会使用列表作为参数. 比如,要测试一个接口的数据,接口返回的数据格式如下: { "code": "20000" ...
随机推荐
- OpenHarmony移植案例: build lite源码分析之hb命令__entry__.py
摘要:本文介绍了build lite 轻量级编译构建系统hb命令的源码,主要分析了_\entry__.py文件. 本文分享自华为云社区<移植案例与原理 - build lite源码分析 之 hb ...
- oracle日常命令
---查询锁表(查出后,再执行查询结果进行释放:可多次查询,存在循环锁表的情况)-- select 'alter system kill session '|| ''''|| sess.sid || ...
- .NET7 gRPC JSON转码+OpenAPI
gRPC JSON转码 gRPC JSON 转码允许浏览器应用调用 gRPC 服务,就像它们是使用 JSON 的 RESTful API 一样. 浏览器应用不需要生成 gRPC 客户端或了解 gRPC ...
- Swagger的介绍
一.Swagger是什么? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务. 二.Swagger 的优势? 支持 API 自动生成同步的在线 ...
- C#调用WPS转换文档到PDF的的实现代码。
1.WPS安装,最好用这个版本别的版本不清楚,安装Pro Plus2016版本. https://ep.wps.cn/product/wps-office-download.html 2.添加相关的引 ...
- oracle 分析函数——ration_to_report 求占有率(百分比)
oracle 的分析函数有很多,但是这个函数总是会忘记,我想通过这种方式能让自己记起来,不至于下次还要百度. 创表.表数据(平时练手的表): prompt PL/SQL Developer impor ...
- JavaEE Day07 HTML
今日内容 Web概念概述 HTML 一.Web概念概述 1. JavaWeb:使用Java语言开发的基于互联网的项目 2.软件架构 C/S架构:Client/Server--- 客户端/服务器端(安卓 ...
- 如何理性看待国内大热的HuTool工具包
一.序言 关于HuTool工具包,相信很多技术朋友都听说甚至使用过.在HuTool之前,已经有比较成熟的工具包比如Apache Common包,谷歌推出的Guava包,他们已经在全世界大范围使用了. ...
- 同时容器,k8s和docker区别是什么? 如何简单理解k8s和docker
1.k8s是一个开源的容器集群管理系统,可以实现容器集群的自动化部署.自动扩缩容.维护等功能. 2.Docker是一个开源的应用容器引擎,开发者可以打包他们的应用及依赖到一个可移植的容器中,发布到流行 ...
- python装饰器初级
global与nonlocal 1.global的作用: 可以在局部空间里直接就该全局名称工具中的数据 代码展示: name = 'moon' #设置了一个全局变量 def fucn(): name ...