十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
Python函数的参数类型主要包括必选参数、可选参数、可变参数、位置参数和关键字参数,本文介绍一下他们的定义以及可变数据类型参数传递需要注意的地方。
创新互联公司是一家专业从事网站建设、网络营销、微信小程序、网站运营为一体的建站企业;在网站建设告别千篇一律,告别似曾相识,这一次我们重新定义网站建设,让您的网站别具一格。成都响应式网站建设,实现全网营销!一站适应多终端,一样的建站,不一样的体验!
必选参数(Required arguments)是必须输入的参数,比如下面的代码,必须输入2个参数,否则就会报错:
其实上面例子中的参数 num1和num2也属于关键字参数,比如可以通过如下方式调用:
执行结果:
可选参数(Optional arguments)可以不用传入函数,有一个默认值,如果没有传入会使用默认值,不会报错。
位置参数(positional arguments)根据其在函数定义中的位置调用,下面是pow()函数的帮助信息:
x,y,z三个参数的的顺序是固定的,并且不能使用关键字:
输出:
在上面的pow()函数帮助信息中可以看到位置参数后面加了一个反斜杠 / ,这是python内置函数的语法定义,Python开发人员不能在python3.8版本之前的代码中使用此语法。但python3.0到3.7版本可以使用如下方式定义位置参数:
星号前面的参数为位置参数或者关键字参数,星号后面是强制关键字参数,具体介绍见强制关键字参数。
python3.8版本引入了强制位置参数(Positional-Only Parameters),也就是我们可以使用反斜杠 / 语法来定义位置参数了,可以写成如下形式:
来看下面的例子:
python3.8运行:
不能使用关键字参数形式赋值了。
可变参数 (varargs argument) 就是传入的参数个数是可变的,可以是0-n个,使用星号( * )将输入参数自动组装为一个元组(tuple):
执行结果:
关键字参数(keyword argument)允许将任意个含参数名的参数导入到python函数中,使用双星号( ** ),在函数内部自动组装为一个字典。
执行结果:
上面介绍的参数可以混合使用:
结果:
注意:由于传入的参数个数不定,所以当与普通参数一同使用时,必须把带星号的参数放在最后。
强制关键字参数(Keyword-Only Arguments)是python3引入的特性,可参考:。 使用一个星号隔开:
在位置参数一节介绍过星号前面的参数可以是位置参数和关键字参数。星号后面的参数都是强制关键字参数,必须以指定参数名的方式传参,如果强制关键字参数没有设置默认参数,调用函数时必须传参。
执行结果:
也可以在可变参数后面命名关键字参数,这样就不需要星号分隔符了:
执行结果:
在Python对象及内存管理机制中介绍了python中的参数传递属于对象的 引用传递 (pass by object reference),在编写函数的时候需要特别注意。
先来看个例子:
执行结果:
l1 和 l2指向相同的地址,由于列表可变,l1改变时,l2也跟着变了。
接着看下面的例子:
结果:
l1没有变化!为什么不是[1, 2, 3, 4]呢?
l = l + [4]表示创建一个“末尾加入元素 4“的新列表,并让 l 指向这个新的对象,l1没有进行任何操作,因此 l1 的值不变。如果要改变l1的值,需要加一个返回值:
结果:
下面的代码执行结果又是什么呢?
执行结果:
和第一个例子一样,l1 和 l2指向相同的地址,所以会一起改变。这个问题怎么解决呢?
可以使用下面的方式:
也可以使用浅拷贝或者深度拷贝,具体使用方法可参考Python对象及内存管理机制。这个问题在Python编程时需要特别注意。
本文主要介绍了python函数的几种参数类型:必选参数、可选参数、可变参数、位置参数、强制位置参数、关键字参数、强制关键字参数,注意他们不是完全独立的,比如必选参数、可选参数也可以是关键字参数,位置参数可以是必选参数或者可选参数。
另外,python中的参数传递属于对象的 引用传递 ,在对可变数据类型进行参数传递时需要特别注意,如有必要,使用python的拷贝方法。
参考文档:
--THE END--
在Python 3.7及以上版本中,math.comb()函数用于计算组合数,并返回一个整数。如果传入的参数不合法,例如列表中的元素是负数,那么函数将引发ValueError异常。如果参数的值太大,导致计算结果超出了Python可以表示的最大整数范围,那么函数将返回OverflowError异常。
如果math.comb(f1(LIST), f2(LIST))返回0,有可能是以下几个原因之一:
f1(LIST)和f2(LIST)的返回值之一是0,那么它们相乘的结果也会是0。这时,math.comb()函数将返回0。
f1(LIST)和f2(LIST)的返回值之一太大,超出了Python可以表示的最大整数范围。这时,math.comb()函数将返回OverflowError异常。
f1(LIST)和f2(LIST)的返回值之一是负数,这时math.comb()函数将引发ValueError异常。如果没有对异常进行处理,程序将会中断并输出错误信息。
如果你需要进一步确定为什么会返回0,可以打印出f1(LIST)和f2(LIST)的返回值,检查它们是否满足预期。另外,你也可以尝试使用try-except语句捕获ValueError和OverflowError异常,以查找原因并采取相应的措施。例如:
import mathtry:
result = math.comb(f1(LIST), f2(LIST))except ValueError: print("Invalid argument - negative value found in the list")except OverflowError: print("Result is too large to represent as an integer")else: print("Result is:", result)
这样可以让程序更加健壮,并且在出现异常时能够提供有用的提示信息。
”IndexError: list index out of range”这种错误一般有两种情况:
第一种可能情况:list[index], index超出范围,也就是常说的数组越界。
第二种可能情况:list是一个空的,没有一个元素,进行list[0]就会出现该错误,在爬虫问题中很常见,比如有个列表爬去下来为空,统一处理就会报错。
扩展资料:
异常处理特点:
1.在应用程序遇到异常情况(如被零除情况或内存不足警告)时,就会产生异常。
2.发生异常时,控制流立即跳转到关联的异常处理程序(如果存在)。
3.如果给定异常没有异常处理程序,则程序将停止执行,并显示一条错误信息。
4.可能导致异常的操作通过 try 关键字来执行。
5.异常处理程序是在异常发生时执行的代码块。在 C# 中,catch 关键字用于定义异常处理程序。
6.程序可以使用 throw 关键字显式地引发异常。
7.异常对象包含有关错误的详细信息,其中包括调用堆栈的状态以及有关错误的文本说明。
8.即使引发了异常,finally 块中的代码也会执行,从而使程序可以释放资源。
参考资料:百度百科——异常处理
要把代码发现来才知道,以下是常见的错误
下面终于要讲到当你用到更多的Python的功能(数据类型,函数,模块,类等等)时可能碰到的问题了。由于篇幅有限,这里尽量精简,尤其是对一些高级的概念。要想了解更多的细节,敬请阅读Learning Python, 2nd Edition的“小贴士”以及“Gotchas”章节。
打开文件的调用不使用模块搜索路径
当你在Python中调用open()来访问一个外部的文件时,Python不会使用模块搜索路径来定位这个目标文件。它会使用你提供的绝对路径,或者假定这个文件是在当前工作目录中。模块搜索路径仅仅为模块加载服务的。
不同的类型对应的方法也不同
列表的方法是不能用在字符串上的,反之亦然。通常情况下,方法的调用是和数据类型有关的,但是内部函数通常在很多类型上都可以使用。举个例子来说,列表的reverse方法仅仅对列表有用,但是len函数对任何具有长度的对象都适用
不能直接改变不可变数据类型
记住你没法直接的改变一个不可变的对象(例如,元组,字符串):
T = (1, 2, 3)
T[2] = 4 # 错误
用切片,联接等构建一个新的对象,并根据需求将原来变量的值赋给它。因为Python会自动回收没有用的内存,因此这没有看起来那么浪费:
T = T[:2] + (4,) # 没问题了: T 变成了 (1, 2, 4)
使用简单的for循环而不是while或者range
当你要从左到右遍历一个有序的对象的所有元素时,用简单的for循环(例如,for x in seq:)相比于基于while-或者range-的计数循环而言会更容易写,通常运行起来也更快。除非你一定需要,尽量避免在一个for循环里使用range:让Python来替你解决标号的问题。在下面的例子中三个循环结构都没有问题,但是第一个通常来说更好;在Python里,简单至上。
S = "lumberjack"
for c in S: print c # 最简单
for i in range(len(S)): print S[i] # 太多了
i = 0 # 太多了
while i len(S): print S[i]; i += 1
不要试图从那些会改变对象的函数得到结果
诸如像方法list.append()和list.sort()一类的直接改变操作会改变一个对象,但不会将它们改变的对象返回出来(它们会返回None);正确的做法是直接调用它们而不要将结果赋值。经常会看见初学者会写诸如此类的代码:
mylist = mylist.append(X)
目的是要得到append的结果,但是事实上这样做会将None赋值给mylist,而不是改变后的列表。更加特别的一个例子是想通过用排序后的键值来遍历一个字典里的各个元素,请看下面的例子:
D = {...}
for k in D.keys().sort(): print D[k]
差一点儿就成功了——keys方法会创建一个keys的列表,然后用sort方法来将这个列表排序——但是因为sort方法会返回None,这个循环会失败,因为它实际上是要遍历None(这可不是一个序列)。要改正这段代码,将方法的调用分离出来,放在不同的语句中,如下:
Ks = D.keys()
Ks.sort()
for k in Ks: print D[k]
只有在数字类型中才存在类型转换
在Python中,一个诸如123+3.145的表达式是可以工作的——它会自动将整数型转换为浮点型,然后用浮点运算。但是下面的代码就会出错了:
S = "42"
I = 1
X = S + I # 类型错误
这同样也是有意而为的,因为这是不明确的:究竟是将字符串转换为数字(进行相加)呢,还是将数字转换为字符串(进行联接)呢?在Python中,我们认为“明确比含糊好”(即,EIBTI(Explicit is better than implicit)),因此你得手动转换类型:
X = int(S) + I # 做加法: 43
X = S + str(I) # 字符串联接: "421"
循环的数据结构会导致循环
尽管这在实际情况中很少见,但是如果一个对象的集合包含了到它自己的引用,这被称为循环对象(cyclic object)。如果在一个对象中发现一个循环,Python会输出一个[…],以避免在无限循环中卡住:
L = ['grail'] # 在 L中又引用L自身会
L.append(L) # 在对象中创造一个循环
L
['grail', [...]]
除了知道这三个点在对象中表示循环以外,这个例子也是很值得借鉴的。因为你可能无意间在你的代码中出现这样的循环的结构而导致你的代码出错。如果有必要的话,维护一个列表或者字典来表示已经访问过的对象,然后通过检查它来确认你是否碰到了循环。
赋值语句不会创建对象的副本,仅仅创建引用
这是Python的一个核心理念,有时候当行为不对时会带来错误。在下面的例子中,一个列表对象被赋给了名为L的变量,然后L又在列表M中被引用。内部改变L的话,同时也会改变M所引用的对象,因为它们俩都指向同一个对象。
L = [1, 2, 3] # 共用的列表对象
M = ['X', L, 'Y'] # 嵌入一个到L的引用
M
['X', [1, 2, 3], 'Y']
L[1] = 0 # 也改变了M
M
['X', [1, 0, 3], 'Y']
通常情况下只有在稍大一点的程序里这就显得很重要了,而且这些共用的引用通常确实是你需要的。如果不是的话,你可以明确的给他们创建一个副本来避免共用的引用;对于列表来说,你可以通过使用一个空列表的切片来创建一个顶层的副本:
L = [1, 2, 3]
M = ['X', L[:], 'Y'] # 嵌入一个L的副本
L[1] = 0 # 仅仅改变了L,但是不影响M
L
[1, 0, 3]
M
['X', [1, 2, 3], 'Y']
切片的范围起始从默认的0到被切片的序列的最大长度。如果两者都省略掉了,那么切片会抽取该序列中的所有元素,并创造一个顶层的副本(一个新的,不被公用的对象)。对于字典来说,使用字典的dict.copy()方法。
静态识别本地域的变量名
Python默认将一个函数中赋值的变量名视作是本地域的,它们存在于该函数的作用域中并且仅仅在函数运行的时候才存在。从技术上讲,Python是在编译def代码时,去静态的识别本地变量,而不是在运行时碰到赋值的时候才识别到的。如果不理解这点的话,会引起人们的误解。比如,看看下面的例子,当你在一个引用之后给一个变量赋值会怎么样:
X = 99
def func():
... print X # 这个时候还不存在
... X = 88 # 在整个def中将X视作本地变量
...
func( ) # 出错了!
你会得到一个“未定义变量名”的错误,但是其原因是很微妙的。当编译这则代码时,Python碰到给X赋值的语句时认为在这个函数中的任何地方X会被视作一个本地变量名。但是之后当真正运行这个函数时,执行print语句的时候,赋值语句还没有发生,这样Python便会报告一个“未定义变量名”的错误。
事实上,之前的这个例子想要做的事情是很模糊的:你是想要先输出那个全局的X,然后创建一个本地的X呢,还是说这是个程序的错误?如果你真的是想要输出这个全局的X,你需要将它在一个全局语句中声明它,或者通过包络模块的名字来引用它。
默认参数和可变对象
在执行def语句时,默认参数的值只被解析并保存一次,而不是每次在调用函数的时候。这通常是你想要的那样,但是因为默认值需要在每次调用时都保持同样对象,你在试图改变可变的默认值(mutable defaults)的时候可要小心了。例如,下面的函数中使用一个空的列表作为默认值,然后在之后每一次函数调用的时候改变它的值:
def saver(x=[]): # 保存一个列表对象
... x.append(1) # 并每次调用的时候
... print x # 改变它的值
...
saver([2]) # 未使用默认值
[2, 1]
saver() # 使用默认值
[1]
saver() # 每次调用都会增加!
[1, 1]
saver()
[1, 1, 1]
有的人将这个视作Python的一个特点——因为可变的默认参数在每次函数调用时保持了它们的状态,它们能提供像C语言中静态本地函数变量的类似的一些功能。但是,当你第一次碰到它时会觉得这很奇怪,并且在Python中有更加简单的办法来在不同的调用之间保存状态(比如说类)。
要摆脱这样的行为,在函数开始的地方用切片或者方法来创建默认参数的副本,或者将默认值的表达式移到函数里面;只要每次函数调用时这些值在函数里,就会每次都得到一个新的对象:
def saver(x=None):
... if x is None: x = [] # 没有传入参数?
... x.append(1) # 改变新的列表
... print x
...
saver([2]) # 没有使用默认值
[2, 1]
saver() # 这次不会变了
[1]
saver()
[1]
其他常见的编程陷阱
下面列举了其他的一些在这里没法详述的陷阱:
在顶层文件中语句的顺序是有讲究的:因为运行或者加载一个文件会从上到下运行它的语句,所以请确保将你未嵌套的函数调用或者类的调用放在函数或者类的定义之后。
reload不影响用from加载的名字:reload最好和import语句一起使用。如果你使用from语句,记得在reload之后重新运行一遍from,否则你仍然使用之前老的名字。
在多重继承中混合的顺序是有讲究的:这是因为对superclass的搜索是从左到右的,在类定义的头部,在多重superclass中如果出现重复的名字,则以最左边的类名为准。
在try语句中空的except子句可能会比你预想的捕捉到更多的错误。在try语句中空的except子句表示捕捉所有的错误,即便是真正的程序错误,和sys.exit()调用,也会被捕捉到。
python列表索引超出范围解决:j=5是j+1是6,列表索引号是从0开始的,第6位的索引是5。
看看是不是出现逻辑错误,常见的逻辑错误有:条件语句的边界值不正确;函数调用的错误;语句的先后顺序不对;运算符使用不正确;循环语句的初始值与终止值有误。因为del会实时地删掉list里面的内容,list就没有原来那么长了,再索引就会超出范围。
当表中有大量记录时
若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。
这里有几个问题。
1.第一行的line=file.readline() 这一行被浪费了。换句话说,文本中的第一行没有被处理
2.new_list=line.split() 这一行有问题,通常应该加一个判断
if not line.strip():break
因为,文本文件readline,最后一行可能为空行。
你的net_list[2]就是因为空行造成的。所以split出来的结果是长度为0的,空列,当然2就index out of range了。