Python参数类型以及常见的坑详解

作者:李不李多 时间:2023-04-16 13:52:33 

导语

由于之前遇到过几次有关于参数类型的坑,以及经常容易把一些参数类型搞混淆,现在做一下有关参数类型的总结记录以及对之前踩坑经历的分析。

参数类型

首先我们列举一下有关于Python的参数类型,以及实际上的运用和原理。

  • 位置参数(必选参数)

  • 默认参数

  • 可变参数

  • 关键字参数

位置参数(必选参数)

首先是位置参数,同时也被称作必选参数,位置参数很好理解,只要记住这点:

在函数定义时直接给定的此参数名称,调用时按照参数的位置顺序,依次赋予参数值。

示例:


def person_info(name, age):
 print("My name is %s, I am %s years old" % (name, age))

person_info("zhangsan", "49")  
# name,age都是位置参数,按照位置顺序,函数中依次接收参数值。

默认参数

默认参数,默认参数存在许多便利的地方,但是同时也存在许多坑,等到后面我们再去仔细分析下为什么存在这些坑,以下几点我们需要注意的:

  • 可以为一个或者多个参数指定默认值,当调用函数时可以不用传入该参数值,大大降低函数调用的难度。

  • 当需要用传入的参数值代替默认参数的默认值时,可以按照参数位置顺序传入,同时也可以指定参数名传入。

示例:


def person_info(name, age, sex='man'):
 print("My name is %s, I am %s years old, I am %s" % (name, age, sex))

person_info('zhangsan', '15')
person_info('lisi', '15', 'women')
person_info('lisi', '20', sex='women')

可变参数

可变参数,顾名思义就是传入的参数数量是可变的:

可变参数在实际中,传入的数量可以是任意多个,但也可以没有。

而可变参数会在传入函数内部时,是一个tuple的形式。

示例:


def add(*numbers):
 sum = 0
 for i in numbers:
   sum+=i
 return sum

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

numbers=[2,3,4,1,5]
add(*numbers)
# 当传入的参数为list时,会将list中所有的元素作为可变参数,传进去

关键字参数

当可变参数在传入0个或者任意个参数时,这些可变参数会在函数调用时自动组装成一个tuple。而关键字参数也允许你传入0个或者任意个含参数名的参数,这些关键字参数会函数内部自动组装为一个dict。调用函数时,可以只传入必选参数。

扩展函数的功能,**kwargs

示例:


def person_info(**kw):
 for key,value in kw.items():
   print(key, value)

person_info(name='zhangsan', age=15)
person = {'name': 'zhangsan', 'age': 13}
person_info(**person)


命名关键字参数


对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。但是针对到底传入了哪些参数,就需要通过函数内部分析检查。所以命名关键字参数就是限制传入的参数的名字,只能传我已命名关键字参数。



  • 命名关键字参数需要一个特殊分隔符*,分隔符后面的参数会被视为命名关键字参数。


  • 当函数中已经存在一个可变参数,后面跟着的命名关键字参数就不需要一个*特殊分隔符——“”**。


  • 命名关键参数可以有默认值,从而简化调用。


  • 命名关键参数必须传入一个参数名,这和位置参数不同。如果没有传入参数名,调用将会报错。



示例:




def person_info(name, *, age, sex):
 print(name, age, sex)

def person_info2(name, *args, age, sex):
 for i in args:
   print(i)
 print(name, age, sex)

person_info('zhangsan', age=12, sex='man')
person_info2('zhangsan', 'sksks', 'ssk', age=13, sex='man')


参数组合调用规则


在python定义函数过程中,可以用位置参数、默认参数、可变参数、关键字参数、命名关键字参数。这五种参数都可以通过组合使用。需要注意的是:


这五种参数定义的顺序必须是:位置参数、默认参数、可变参数、命名关键字参数、关键字参数。


位置参数和默认参数组合




def Person(name, age=20):
 print(name,age)

Person('zhangsan')
Person('zhangsan', 20)


位置参数、默认参数、可变参数组合




def Person(name, age=20, *args):
 for i in args:
   print(i)
 print(name, age)

Person('zhangsan')
Person('zhangsan', 22, "Beijing")
Person('zhangsan', age=22, 'Shanghai')

位置参数、默认参数、可变参数、命名关键字参数组合


def Person(name, age=20, *args, city, **kwargs):
 for i in args:
   print(i)
 for key,value in kwargs.items():
   print(key, value)
 print(name, age, city)

Person('zhangsan', age=12, 'Author', city='Shanghai', company='Shanghai Software')


关于参数定义的一些坑


默认参数陷阱


关于默认参数陷阱的问题,我们先来看一看一个示例:





def Book(book, book_list=[]):
 print(id(book_list))
 book_list.append(book)
 for book in book_list:
   print(book)
 print(id(book_list))  

test = Book("First One")

输出的结果:

Python参数类型以及常见的坑详解

这个输出的结果应该是意料之中,现在我们这时候再调用Book()方法,看看会发生什么:

Python参数类型以及常见的坑详解

这时候输出结果,竟然把之前的First one都输出,看了他们的id,发现都是同一块内存地址,这时候就开始纳闷了,那么来找找出现这种状况的原因。

经过查阅官方资料发现,这是一段Python官方文档给出的解释:

Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. For example, the following function accumulates the arguments passed to it on subsequent calls:

我们来看看解释分析下,Python官方文档给出的理由就是Python对默认值只计算一次,对于可变对象,在后续调用的情况下会累积传递给他们。而list、dict等这种都属于可变对象。

那么对于这种默认值陷阱,我们是该如何避免造成一些不必要的麻烦呢?大致有两种解决方法:

  • 避免使用可变对象作为默认值。

  • 在参数定义的时候可以使用None对象作为占位符。

对于第二种方法:


def Book(book, book_list=None):
 print(book_list)
 if book_list is None:
   book_list = []
 book_list.append(book)
 for book in book_list:
   print(book)
 print(id(book_list))

test1 = Book('First one')
test2 = Book('Second one')

测试结果:

Python参数类型以及常见的坑详解

慎用变长参数

前面已经介绍过了,Python是支持可变长度的参数列表,可以在函数定义参数时使用*args和**kwargs两个特殊的语法来实现。

那为什么要说慎用变长参数,我总结了一下有以下几个原因:

使用过于灵活。比如在我上面有关不同类型参数组合使用的示例中,在位置参数和默认参数在的情况下,还有可变参数、关键字参数、命名关键字参数。这就很容易是的这个函数的签名不够清晰,调用者需要花费时间去了解你这个方法该如何调用。所以这就很容易使得团队开发中效率低效。

另外一个原因,如果一个函数的列表过于长,虽然可以通过使用*args, **kwargs来简化函数,但同时也意味这个函数或许有更好的实现方式,有重构的必要。

说完了要慎用,在说说看我们常用的变长参数的使用场景:

  • 为函数添加一个装饰器。

  • 如果参数的数目不确定的时候,可以考虑使用变长参数。比如读取一些配置文件中的配置项时。

  • 用来实现函数的多态,或者在继承情况下子类需要调用父类的某些方法。

总结

关于的Python参数类型就写到这里了,刚开始学Python的时候,经常被函数定义的参数类型搞懵,后面看了一些教程,自己在写一些脚本的时候遇到的一些坑,并且在看一些大牛分析背后的原理,后面感觉收获良多。后面干脆想把自己学习过程遇到的东西都整理一下,做个记录,加深理解。

来源:https://blog.51cto.com/mbb97/2412462

标签:python,参数,类型,坑
0
投稿

猜你喜欢

  • MySQL无法创建外键的原因及解决方法

    2024-01-17 00:00:07
  • 实例详解JavaScript中setTimeout函数的执行顺序

    2024-04-22 13:25:09
  • 举例讲解Python中装饰器的用法

    2022-12-26 17:02:23
  • python+Django+pycharm+mysql 搭建首个web项目详解

    2024-01-18 22:18:07
  • python正则表达式常见的知识点汇总

    2023-10-02 18:56:21
  • 通过mysqladmin远程管理mysql的方法

    2024-01-16 15:45:20
  • 由浅到深了解JavaScript类

    2008-06-16 13:20:00
  • python实现一个简单RPC框架的示例

    2023-08-25 11:10:07
  • JS实现控制表格内指定单元格内容对齐的方法

    2024-04-17 09:42:28
  • python实现图片批量压缩程序

    2021-11-27 03:50:11
  • 未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。

    2023-07-01 00:38:21
  • 微信小程序 swiper 组件遇到的问题及解决方法

    2024-04-18 09:40:47
  • Asp截获后台登录密码的代码

    2012-12-04 20:20:38
  • 微信公众号token验证失败解决方案

    2022-01-22 14:33:45
  • Go代码检查的推荐工具及使用详解

    2024-05-09 15:00:11
  • python中asyncore异步模块的实现

    2023-10-23 00:50:07
  • Python实战之外星人入侵游戏示例代码

    2023-12-23 08:18:18
  • Django REST framework视图的用法

    2021-02-10 02:51:49
  • Python+腾讯云服务器实现每日自动健康打卡

    2023-08-18 00:22:44
  • Ubuntu Server 20.04 LTS 环境下搭建vim 编辑器Python IDE的详细步骤

    2023-06-02 05:13:18
  • asp之家 网络编程 m.aspxhome.com