设为首页 收藏本站
查看: 1041|回复: 0

[经验分享] 深入Python函数定义

[复制链接]

尚未签到

发表于 2015-12-2 10:27:19 | 显示全部楼层 |阅读模式
  在Python中,你也可以定义包含若干参数的函数。这里有三种可用的形式,也可以混合使用。

1. 默认参数值
  最常用的一种形式是为一个或多个参数指定默认值。这会创建一个可以使用比定义时允许的参数更少的参数调用的函数,例如:
  

def ask_ok(prompt, retries = 4, complaint = "Yes or no, please!"):  while True:
  ok = input(prompt)
  if ok in ('y', 'ye', 'yes'):
  return True
  if ok in ('n' ,'no', 'nop', 'nope'):
  return False
  retries = retries - 1
  if retries < 0:
  raise IOError('refusenik user')
  print(complaint)
  

  

  这个函数可以通过几种不同的方式调用:


  • 只给出必要的参数:ask_ok('Do you really wnat to quit?')  

  • 只给出一个可选的参数:ask_ok('Ok to overwrite the file',2)  

  • 或者给出所有的参数:ask_ok('OK to overwrite the file?',2,'Come on, only yes or no!'),
  这个例子还介绍了in关键字。它测定序列中是否包含某个确定的值:ok in ('y', 'ye', 'yes')
  默认值在函数定义作用被解析,如下所示:
  

i = 5  
def f(arg = i):
  print(arg)
  
i = 6
  
f()
  

  将会输出5
  重要警告:默认值只被赋值一次。这使得当默认值是可变对象时会有所不同,比如列表、字典或者大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)付给它的参数:
  

def f(a, L = []):  L.append(a)
  return L
  
print(f(1))
  
print(f(2))
  
print(f(3))
  

  这将输出:
  

[1]  
[1, 2]
  
[1, 2, 3]
  

  如果你不想让默认值在后续调用中累积,你可以像下面一样定义函数:
  

def f(a, L=None):  if L is None:
  L = []
  L.append(a)
  return L
  

2. 关键字参数
  函数可以通过关键字参数的形式来调用,形如keyword = value。例如:以下的函数:
  

def parrot(voltage, state = 'a stiff', action = 'voom', type = 'Norwegian Blue'):  

  接受一个必选的参数(voltage)以及三个可选参数(state,action和type)。可以用以下的任一方法调用:
  

parrot(1000)  
parrot(voltage = 1000)
  
parrot(voltage = 10000, action = 'VOOOM')
  
parrot(action = 'VOOOOM', voltage = 1000) # action 写在前面也是OK的!
  
parrot('a million', 'bereft of life', 'jump') # voltage = 'a milion'
  
parrot('a thousand', state = 'pushing up the daisies') # voltage = 'a thousand'
  

  不过以下几种调用是无效的:
  

parrot() # voltage必须有值  
parrot(voltage = 5.0, 'dead') # 一旦有一个参数是通过关键字指定的,后面的也必须都是
  
parrot(110, voltage = 220) # 两个voltage的值
  
parrot(acotr = 'Jonh Cleese') # 没有voltage的值
  

  通常,参数列表必须(先书写)位置参数然后才是关键字参数,这里关键字必须来自于形参名字。形参是否有一个默认值并不重要。任何参数都不能被多次赋值——在同一个调用中,与位置参数相同的形参名字不能用作关键字。
  引入一个形如**name的参数时,它接收一个字典,该字典包含了所有未出现的形式参数中关键字参数。这里可能还会组合使用一个形如*name的形式参数,它接收一个元组,包含了所有没有出现在形式参数列表中的参数值(*name必须出现在**name之前)。例如,我们这样定义一个函数:
  

  
def cheeseshop(kind, *arguments, **keywords):
  print("-- Do you have any", kind, "?")
  print("-- I'm sorry, we're all out of", kind)
  for arg in arguments:
  print(arg)
  print("-"*40) # 打印40个’-‘
  keys = sorted(keywords.keys()) # 按键值排序
  for kw in keys:
  print(kw, ":", keywords[kw])
  

  它可以像这样调用:
  

cheeseshop("Limburger", "It's very runny, sir.",  "It's really very, VERY runny, sir.",
  shopkeeper="Michael Palin",
  client="John Cleese",
  sketch="Cheese Shop Sketch")
  

3. 可变参数列表
  最后,一个最不常用的选择是可以让函数调用可变个数的参数。这些参数被包装进一个元组。在这些可变个数的参数之前,可以有零到多个普通的参数:
  

def write_multiple_items(file, separator, *args):  file.write(separator.join(args)) # 用separator符号将arg里的内容连在一起
  

  通常这些可变参数是参数列表的最后一个,因为它们将所有剩余的输入参数传递给函数。任何出现在args后的参数是关键字参数,这意味着,他们只能被用作关键字,而不是位置参数:
  

>>> def concat(*args, sep="/"):  
...    return sep.join(args)
  
...
  
>>> concat("earth", "mars", "venus")
  
'earth/mars/venus'
  
>>> concat("earth", "mars", "venus", sep=".")
  
'earth.mars.venus'
  

4. 参数列表的分拆
  另有一种相反的情况:当你要传递的参数已经是一个列表,但是要调用的函数却接受分开一个个的参数值,这时候你要把已有的列表拆开来,例如内建函数range()需要两个独立的参数range(start, end)。你可以在调用函数时加一个*把已有的列表拆开:
  

>>>list(range(3, 6))  
[3, 4 ,5]
  
>>> args = [3, 6]
  
>>> list(range(*args))
  
[3, 4, 5]
  

  以同样的方式,可以使用**操作符分拆关键字参数为字典:
  

>>> def parrot(voltage, state='a stiff', action='voom'):  
...     print("-- This parrot wouldn't", action, end=' ')
  
...     print("if you put", voltage, "volts through it.", end=' ')
  
...     print("E's", state, "!")
  
...
  
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
  
>>> parrot(**d)
  
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
  

5. Lambda形式
  出于实际需要,有几种通常在函数式编程语言例如 Lisp 中出现的功能加入到了 Python。通过 lambda关键字,可以创建短小的匿名函数。这里有一个函数返回它的两个参数的和:lambda a, b: a+b。 Lambda 形式可以用于任何需要的函数对象。出于语法限制,它们只能有一个单独的表达式。语义上讲,它们只是普通函数定义中的一个语法技巧。类似于嵌套函数定义,lambda 形式可以从外部作用域引用变量:
  

>>> def make_incrementor(n):  
...     return lambda x: x + n
  
...
  
>>> f = make_incrementor(42)
  
>>> f(0)
  
42
  
>>> f(1)
  
43

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-146232-1-1.html 上篇帖子: python机器学习工具包 下篇帖子: awk,perl,python的命令行参数处理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表