TIOBE排行榜是程序开发语言的流行使用程度的有效指标,对世界范围内开发语言的走势具有重要参考意义。随着数据挖掘、机器学习和人工智能相关概念的风行,Python一举收获2018年年度语言,这也是Python继2007和2010年之后第三次问鼎榜单。前阵子在GitHub创建Profile README时惊觉Python是我的第二高频语言,回想第一次见到positional only parameter传参方式时一头雾水的查找资料,借由周末闲暇,将Python函数传参的部分语法糖做一次总结。

Python是Guido van Rossum(以下简称GvR)在1989年圣诞节创造的编程语言,支持多种编程范式,1991年对外发布了第一个版本。随后的2000年发布了Python2,2008年发布了不完全向前兼容的Python3,Python语言目前由Python基金会进行维护,2020年1月1日Python2正式落幕,因此本文所述内容均基于Python3。

在Python中将面向过程方式声明的函数(即不归属于类)称为函数(function),而面向对象方式声明的函数称为方法(method)。

语法糖1:

实例方法第一个参数默认为当前实例对象,类方法第一个参数默认为当前类对象,静态方法没有该约束。

# 函数
def greeting():
print("function")


class Human:
# 实例方法
def greeting(self):
print("instance method")

# 类方法
@classmethod
def write(cls):
print("class method")

# 静态方法
@staticmethod
def read():
print("static method")

语法糖2:

参数可以具备默认值,对比Objective-C由于这项特性的缺失需要实现构造方法和便利构造方法。

def greeting(name = "Jack Ma"):
print("Hello", name)

>>> greeting()
Hello Jack Ma
>>> greeting("Pony Ma")
Hello Pony Ma

语法糖3:

通过*args表示可变参数。

def calc(name, *args):
spent = 0
for v in args:
spent += v
print(name, "spent money:", spent)

>>> calc("Jack Ma", 1000000, 2000000)
Jack Ma spent money: 3000000

传入的参数通过type(args)可以检查类型为元组(tuple),除了函数声明外函数调用亦然。

>>> args = (1000000, 2000000, 3000000) # [1, 2, 3]同理
>>> calc("Jack Ma", *args)
Jack Ma spent money: 6000000

通过**kwargs以键值对的形式表示可变参数。

def calc(name, **kwargs):
spent = name + " spent on:"
for k, v in kwargs.items():
spent += "%s=%s," % (k, v)
print(spent)


>>> calc("Jack Ma", eating=10000, shopping=20000)
Jack Ma spent on:eating=10000,shopping=20000

同理,函数调用亦然。

>>> kwargs = {"eating":10000, "shopping":20000}
>>> calc("Jack Ma", **kwargs)
Jack Ma spent on:eating=10000,shopping=20000

自Python1起就支持通过位置和参数名称两种方式传递参数,如对于原型为def add(x, y)的函数,同时支持以下两种调用方式。

add(1, 2)
add(x=1, y=2)

语法糖4:

Keyword-Only Arguments (PEP-3012)

函数声明时,参数列表中单独的*表示在此之后的参数仅支持通过名称进行传递。通过这个语法可以在可变参数列表之后传递其他参数。

def compare(a, b, *, key=None):
pass

>>> compare(1, 2, 3) # 调用失败
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: compare() takes 2 positional arguments but 3 were given
>>> compare(1, 2, key=3) # 调用成功

语法糖5:

Positional-Only Parameters (PEP-570)

函数声明时,参数列表中单独的/表示在此之前的参数仅支持通过位置进行传递。这个语法主要解决部分函数的参数没有实际意义,后续可能会进行修改,避免通过名称传递参数在名称修改后失效。比如int(x="1")中x并没有实际意义,而且相比int("1")可读性有所不足。

def name(positional_only_parameters, /, positional_or_keyword_parameters,
*, keyword_only_parameters):
pass

此外,官方文档表述这个语法还解决了某个边界条件下的调用失败。对于以下函数:

def foo(name, **kwargs):
return 'name' in kwargs

当我们传递的kwargs拥有一个"name"的key时会调用失败,如下。

>>> foo(1, **{'name': 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for argument 'name'

通过以下方式可以解决这个问题。

def foo(name, /, **kwargs):
return 'name' in kwargs

语法糖6:

如何修改参数的引用,官方文档解释称:Python中参数的传递通过值传递(但引用是通过值传递的,参考链接2),最简单的方式是将入参按顺序以元组进行返回。

  • https://docs.python.org/zh-cn/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference

  • https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference

语法糖7:

由于Python的first-class function特性,函数作为一等公民可以像其他类型一样进行传递和赋值。比如max函数原型可以传入一个用于比较的函数,当然函数也可以被重新赋值。

>>> max=min
>>> max(19,9)
9

全局函数和关键字有时候会不易分辨,比如print在Python2中是关键字,而在Python3中是内置函数。可以通过下列方式获取关键字列表。

>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

语法糖8:

类型标注(Type Hint)通过:type表示参数类型,由于Python动态类型的特性Python 运行时并不强制标注函数和变量类型,类型标注可被用于IDE等第三方工具。如下:

def greeting(name: str) -> str:
return 'Hello ' + name

详细内容可以参考官方中文文档:

  • https://docs.python.org/zh-cn/3/library/typing.html

回想第一次在Python作者GvR的500-lines-of-code中见到 Keyword-Only Arguments的用法几度无法理解代码为什么能够正常运行,顺便一提,该项目同时也是绝佳的编程学习材料。

行文至此语法糖的数量超出了我的预期,本篇文章创作期间我惊喜的发现官方已经宣告了Python2的落幕,官方文档提供了简体中文版本,而Python也已经发布了3.9版本,被称为BDFL的GvR也在2018年通过邮件组宣布了权力的交接。

通过TIOBE长期榜单变化可以发现,Python作为这个榜单的常青树且仍然保持着上升趋势,身边也有不少人自学这门语言。文章的最后摘录Python之禅与各位共勉。

>>> python3
>>> import this
The Zen of Python, by Tim Peters


Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

想要获取更多Python学习资料可以加我QQ:2955637827

悉数 Python 函数传参的语法糖的更多相关文章

  1. python函数传参是传值还是传引用?

    首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...

  2. python函数传参和返回值注意事项

    函数传参 空参数 定义函数时括号里面没有形参,调用时不用传参. def func(): print('null para.') # 调用 func() 位置传参 规定形参的数量,调用时必须传递相同数量 ...

  3. python函数 传参的多种方式 解读

    1.函数的参数在哪里定义 在python中定义函数的时候,函数名后面的括号里就是用来定义参数的,如果有多个参数的话,那么参数之间直接用逗号, 隔开 案列: 2.带参数的函数调用: 函数定义了参数,那么 ...

  4. python函数--传参

    一.位置参数 二.关键字参数 三.默认参数 四.任意数量的位置参数: 1. *x 2. 传入的多个参数,最终合并成一个元组 3. 之后的参数必须用关键字参数 五.任意数量的关键字参数 1. **x 2 ...

  5. 『Python × C++』函数传参机制学习以及对比

    一.Python函数传参 在python中,函数传参实际上传入的是变量的别名,由于python内在的变量机制(名称和变量值相互独立),只要传入的变量不可变(tuple中的元素也要是不可变的才行),那么 ...

  6. python中给函数传参是传值还是传引用

    首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...

  7. 函数传参传的是啥的思考【java Python】

    今天看<java 核心 卷1>的时候,作者提到了函数传参的问题,他提到,java传参,传的是值,而不是引用,然后,函数将要传的实参的值(如果实参是基本数据类型,那么就是值.如果实参是对象, ...

  8. JS——变量和函数的预解析、匿名函数、函数传参、return

    JS解析过程分为两个阶段:编译阶段.执行阶段.在编译阶段会将函数function的声明和定义都提前,而将变量var的声明提前,并将var定义的变量赋值为undefined. 匿名函数: window. ...

  9. pytest_函数传参和firture传参数request

    前言为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数. 比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登陆函数就行. ...

随机推荐

  1. C#中的WinForm问题——如何设置窗体的大小为超过屏幕显示的最大尺寸?

    今天在学习C#时遇到了一个问题,在此记录下来,留作日后总结复习之用,也分享给有同样问题和困扰的园友. 我手上的电脑是笔记本电脑,屏幕的尺寸大小为1366*768,然而项目所使用的屏幕大小为1920*1 ...

  2. VS Code C++ 项目快速配置模板

    两个月前我写过一篇博客 Windows VS Code 配置 C/C++ 开发环境 ,主要介绍了在 VS Code 里跑简单 C 程序的一些方法.不过那篇文章里介绍的方法仅适用于单文件程序,所以稍微大 ...

  3. CoProcessFunction实战三部曲之二:状态处理

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. 【2020.12.01提高组模拟】卡特兰数(catalan)

    题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...

  5. 使用douban源下载python包

    需求 python默认使用国外源下载依赖包,由于一些其它因素(例如网络差了,国外机器炸了,我们强大的祖国了...)经常导致下载安装失败,so出现了以豆瓣为主的国内下载源 如何使用豆瓣进行下载 豆瓣下载 ...

  6. Apache Flink 如何正确处理实时计算场景中的乱序数据

    一.流式计算的未来 在谷歌发表了 GFS.BigTable.Google MapReduce 三篇论文后,大数据技术真正有了第一次飞跃,Hadoop 生态系统逐渐发展起来. Hadoop 在处理大批量 ...

  7. CentOS下Mysql的操作

    重启Mysql的各种方法 1.通过rpm包安装的MySQL service mysqld restart /etc/inint.d/mysqld start 2.从源码包安装的MySQL // lin ...

  8. PyQt(Python+Qt)学习随笔:QTreeView树形视图的headerHiden属性

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTreeView树形视图的headerHiden属性用于控制视图中是否隐藏标题,为True隐藏,否 ...

  9. PyQt(Python+Qt)帮助文档官网及文档下载

    一.帮助文档下载 老猿在网上找到一个Qt 5.9的帮助文档,没有找到最新版的,并且这个文档官网上没有下载,不知道源头在哪里可以下载. 文档存放在百度网盘: 链接:https://pan.baidu.c ...

  10. 1、tensorflow 框架理解

    2020/10/31 参考:https://blog.csdn.net/mzpmzk/article/details/78636127 1. 两大步骤:定义图define the graph, 进行计 ...