点击关注我哦

一篇文章带你了解函数声明时的优雅操作

4. 错误使用默认值

在编写函数时,Python允许我们为某些参数设置一些默认值。许多内置函数也使用此功能。考虑下面的示例。我们可以使用range()函数创建一个列表对象,该函数具有常规语法range(start,stop,step)。如果省略,默认步骤参数将使用一个。但是,我们可以在以下代码中显式设置step参数(类似于第2个示例):

>>> list(range(5, 15))
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]>>> list(range(5, 15, 2))
[5, 7, 9, 11, 13]

但是,当我们编写包含具有可变数据类型的默认值的函数时,事情会变得棘手。当我们说可变数据时,是指Python对象在创建后就可以更改,例如列表,字典和集合。要了解有关Python数据可变性的更多信息,请参阅我的上一篇文章。考虑以下有关在函数中使用默认值和可变参数的简单示例:

>>> def append_score(score, scores=[]):
...     scores.append(score)
...     print(scores)
...
>>> append_score(98)
[98]
>>> append_score(92, [100, 95])
[100, 95, 92]
>>> append_score(94)
[98, 94]

当我们尝试附加分数98时,将打印出预期结果,因为我们省略了分数参数,并且期望使用空列表。当我们尝试将得分92附加到[100,95]列表中时,结果[100,95,92]也符合预期。但是,当我们尝试附加分数94时,我们中的某些人可能会期望结果为[94],但事实并非如此。为什么会发生这种情况?

这是因为Python中的函数也是一等公民,并且被视为常规对象(请参阅我之前的文章,关于函数是Python中的对象)。这意味着在定义函数时,将创建一个对象,包括该函数的默认变量。让我们看一下有关这些概念的代码片段:

>>> def append_score(score, scores=[]):
...     scores.append(score)
...     print(f'scores: {scores} & id: {id(scores)}')
...
>>> append_score.__defaults__
([],)
>>> id(append_score.__defaults__[0])
4650019968
>>> append_score(95)
scores: [95] & id: 4650019968
>>> append_score(98)
scores: [95, 98] & id: 4650019968

我们修改了先前的功能,使其能够输出分数列表的内存地址。如您所见,在调用函数之前,我们可以找到函数参数的默认值及其访问__default__属性的内存地址。两次调用函数后,具有相同存储地址的相同列表对象已更新。

那么最好的做法是什么?我们应该使用None作为可变数据类型的默认值,这样,在声明函数时,函数不会实例化可变对象。调用函数时,我们可以根据需要创建可变对象。有关其他信息,请参见下面的代码。现在,一切都按预期工作:

>>> def append_score(score, scores=None):
...     if not scores:
...         scores = []
...     scores.append(score)
...     print(scores)
...
>>> append_score(98)
[98]
>>> append_score(92, [100, 95])
[100, 95, 92]
>>> append_score(94)
[94]

5. 滥用* args和** kwargs

Python允许我们通过支持可变数量的参数来编写灵活的函数。如果您还记得的话,您一定已经在某些库的文档中的某些地方看到了* args和* kwargs。本质上,* args指的是数量不确定的位置参数,而** kwargs指的是数量不确定的关键字参数。

在Python中,位置参数是根据其位置传递的参数,而关键字参数是根据其指定的关键字传递的参数。下面来看一个简单的例子:

>>> def add_numbers(num0, num1, num2=2, num3=3):
...     outcome = num0 + num1 + num2 + num3
...     print(f"num0={num0}, num1={num1}, num2={num2}, num3={num3}")
...     return outcome
...
>>> add_numbers(0, 1)
num0=0, num1=1, num2=2, num3=3
6
>>> add_numbers(0, 1, num3=4, num2=5)
num0=0, num1=1, num2=5, num3=4
10

在函数add_numbers中,num0和num1是位置参数,而num2和num3是关键字参数。需要注意的一件事是,您可以更改关键字参数之间的顺序,但不能更改位置参数和关键字参数之间的顺序。

尽管* args和* kwargs的可用性使我们能够编写更灵活的Python函数,但是滥用它们可能会导致函数混乱。之前,我提到我们可以使用pandas库进行数据处理,并简要提到了read_csv函数,该函数读取CSV文件。该函数共有49个参数:一个位置参数和48个关键字参数。从理论上讲,我们可以通过执行以下操作使列表更短:

pandas.read_csv(filepath_or_buffer: Union[str, pathlib.Path, IO[~AnyStr]], **kwargs)

但是,在此功能的实际实现中,我们仍然必须拆开* kwarg文件,并弄清楚如何正确读取CSV文件。为什么这些经验丰富的Python开发人员愿意列出所有这些关键字参数?这是因为他们了解以下原则:

“Explicit is better than implicit.” —The Zen of Python

尽管使用** kwargs可以为我们在函数声明的第一行中节省一些时间,但代价是我们的代码变得不太明确。 同样的想法也适用于* args。 如上所述,如果我们在代码共享环境中工作,我们总是希望我们的代码是显式的,从而易于理解。 因此,我们尽可能避免使用* args和** kwargs编写更明确的代码。

总结

在本文中,我们回顾了Python程序员可能在其代码中犯的五个常见错误。 尽管您可以通过忽略项目中的这些错误来拥有自己的编码风格,但是您的代码可能变得难以理解,并且长期可维护性较低。 因此,如果可能的话,我们所有人都可能希望避免这些错误并提高代码的可读性,从而提高共享性。

·  END  ·

HAPPY LIFE

在Python中“准确而优雅”的声明函数(二)相关推荐

  1. 在Python中“准确而优雅”的声明函数(一)

    点击关注我哦 一篇文章带你了解函数声明时的优雅操作 函数是所有程序的关键组成部分,正确的函数是一种编写可读且可维护的代码的实用方法.但是未正确声明函数,则将把代码将变得难以阅读,并且长期可维护性很低. ...

  2. python中变量不需要事先声明_第二章 Python 变量

    2.1  Python变量 在 Python 中变量不需要事先声明变量名及其类型,直接赋值即可创建各种变量(不要使用关键字为变量名),例如: >>>x = 4 >>> ...

  3. python中的变量不需要声明

    python中的变量不需要声明. 每个变量在使用前都必须赋值,变量复制以后该变量才会被创建.在Python中,变量就是变量,它没有类型, 我们所说的"类型"是变量所指的内存中对象的 ...

  4. python关键字define_在Python中,使用关键字define定义函数。

    在Python中,使用关键字define定义函数. 以下属于生药学有效性评价的是A:有效成分定量分析B:限量检查C:重金属检测D:基原鉴定 若有如下定义和语句:A:7B:12C:8D:9 图示电路中的 ...

  5. python中的map,feilter,和reduce函数

    python中的map,feilter,和reduce函数 map() map()的原型是map(function, iterable, -) 参数 function: 传的是一个函数名,可以是pyt ...

  6. 从Python中的另一个文件调用函数

    本文翻译自:Call a function from another file in Python Set_up: I have a .py file for each function I need ...

  7. python列表去重函数_对python中两种列表元素去重函数性能的比较方法

    测试函数: 第一种:list的set函数 第二种:{}.fromkeys().keys() 测试代码: #!/usr/bin/python #-*- coding:utf-8 -*- import t ...

  8. python命名规则数字开头的成语_浅谈Python中带_的变量或函数命名

    搜索热词 Python 的代码风格由 PEP 8 描述.这个文档描述了 Python 编程风格的方方面面.在遵守这个文档的条件下,不同程序员编写的 Python 代码可以保持最大程度的相似风格.这样就 ...

  9. Python中求最大值和最小值max()函数、min()函数

    [小白从小学Python.C.Java] [Python全国计算机等级考试] [Python数据分析考试必会题] ● 标题与摘要 Python中求最大值和最小值 max()函数.min()函数 ● 选 ...

最新文章

  1. 怎么看电脑电源多少w_电脑电源供电不足会怎么样 电脑电源供电不足坏处介绍【详解】...
  2. hdu1255 扫描线,矩形重叠面积(两次以上)
  3. 事务对性能影响_MySQL数据库性能优化史诗级大总结
  4. 野蛮愚昧的词过滤,咱是技术网站吗?
  5. 安装Visio2010 64bit时提示不能安装32位版本的Office 2010 ,因为您当前已经安装了64位Office产品的解决方法(亲测可行)
  6. IGBT简介、结构及原理
  7. GRE填空词汇专项训练
  8. Iframe用法总结
  9. DIM抠图网络 Deep Image Matting 论文笔记
  10. Web 服务器配置和管理
  11. XFire野猪书-XFire开发指南第二版
  12. Linux nodejs 安装以及配置环境
  13. FPGA 20个例程篇:9.DDR3内存颗粒初始化写入并通过RS232读取(下)
  14. iOS常见面试题总结
  15. 刘顺琦 - CSCI 561 mid 1definition
  16. 关于keil编译显示Flash Download failed -Could not load file xxxx.axf
  17. C++各大有名库的介绍(一)
  18. arp欺骗和dns欺骗
  19. js获取当前日期及下一天日期
  20. 一起学英语第二季第六期

热门文章

  1. Spring aop 原始的工作原理的理解
  2. PHP之微信公众平台开发
  3. 卸载亚信科技安全助手
  4. 串连字符串strcat
  5. “Microsoft Office Word 遇到问题需要关闭。我们对此引起的不便表示抱歉”处理方法之一
  6. Node进阶—事无巨细手写Koa源码
  7. Python3.5 email发送邮件,包含txt、图片、HTML、附件
  8. 如何将sql2000备份数据库还原到sql2008中
  9. 2. 查询教师编号、教师姓名、课程名称、平均成绩。
  10. defaultbutton IE11下不起作用