由于之前遇到过几次有关于参数类型的坑,以及经常容易把一些参数类型搞混淆,现在做一下有关参数类型的总结记录以及对之前踩坑经历的分析。
首先我们列举一下有关于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')
可变参数,顾名思义就是传入的参数数量是可变的:
示例:
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。调用函数时,可以只传入必选参数。
示例:
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")
输出的结果:
这个输出的结果应该是意料之中,现在我们这时候再调用Book()方法,看看会发生什么:
这时候输出结果,竟然把之前的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等这种都属于可变对象。 那么对于这种默认值陷阱,我们是该如何避免造成一些不必要的麻烦呢?大致有两种解决方法:
对于第二种方法:
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是支持可变长度的参数列表,可以在函数定义参数时使用*args和**kwargs两个特殊的语法来实现。 那为什么要说慎用变长参数,我总结了一下有以下几个原因:
说完了要慎用,在说说看我们常用的变长参数的使用场景:
关于的Python参数类型就写到这里了,刚开始学Python的时候,经常被函数定义的参数类型搞懵,后面看了一些教程,自己在写一些脚本的时候遇到的一些坑,并且在看一些大牛分析背后的原理,后面感觉收获良多。后面干脆想把自己学习过程遇到的东西都整理一下,做个记录,加深理解。 下面是我参考的一些博客文章: https://www.liaoxuefeng.com/wiki/1016959663602400/1017261630425888 http://cenalulu.github.io/python/default-mutable-arguments/ https://www.cnblogs.com/Clonglegs/p/9564873.html https://blog.csdn.net/u014745194/article/details/70158926