#2 python函数定义

python中函数的定义使用 def 语句,依次写函数名,括号,参数, 冒号 :,然后缩进语句块,有返回值的使用return语句,如果没有返回值的,可以写'return',或者'return None'

def my_fun(x):
  if x >=0:
    return x
  else:
    return -x

一.空函数

python中使用 pass 语句

def none_fun:
  pass

这样有些代码如果没有想好就可以先跳过,当然 pass 语句还可以用于其它语句中

if x >= 100:
  pass

二.函数参数

1.默认参数

python的默认参数和C#中的默认参数很类似,一般将变化小的参数写在后面,可以提供有名实参而不用考虑参数的顺序等

def enroll(name, gender, age=6, city='wuhan'):
  print('name:', name)
  print('gender:', gender)
  print('age:', age)
  print('city:', city)

enroll('james', 'F')
enroll('kobe', 'M', city='Los Angle')

值得注意的是:默认参数必须指向不变对象

如果指向的是可变对象,比如list类型,则可能出现意想不到的结果

def add_end(L=[]):
  L.append('END')
  return L

>>> add_end()
['END']

>>> add_end()
['END', 'END']

这是因为python函数在定义时,默认参数L的值被计算出来了,即[],因为L也是一个变量,指向对象[],每次调用该函数,如果改变L的内容,下次调用时,默认参数的内容就改变了

可以改为:

# 将默认参数指向一个不可变对象None
def add_end(L=None):
  if L is None:
    L = []
  L.append('END')  
  return L

>>> add_end()
['END']

>>> add_end()
['END']

使用 is 关键词,这关键词和js中一致

2.可变参数*

其实就是js中的spread操作符,python中使用 * 表示, 可变参数在函数调用时实际上自动组装成一个元组tuple

def calc(*numbers):
  sum = 0
  for n in numbers:
    sum += n * n
  return sum

# 对于一般的数,可以直接传入
calc(1, 2)    
calc(1, 2, 3)

# 对于list tuple等集合元素,可以像js中先展开
# list [1, 2, 3]
L = [1, 2, 3]
calc(*L)

T = (1, 2, 3)
calc(*T)

3.关键字参数 **

关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装成一个 dict, 表示方式为 **

示例:

def person(name, age, **kw):
  print('name:', name, 'age:', age, 'other:', kw)

# 关键字参数自动组装成字典dict
>>> person('james', 28, city='wuhan', hobby='base')
name: james, age: 28, other: {city: 'wuhan', hobby='base'}

# 可以直接传入一个字典dict, 但是需要在字典前保留 '**'
>>> info = {gender: 'M', hobby: 'basketball'}
>>> person('james', 28, **info)
name: james, age: 28, other: {gender: 'M', hobby: 'basketball'}

值得注意的是,传入到函数中的info字典只是外部定义的info的拷贝,函数中的info改变不会影响到外部的info字典

4.命名关键字参数

用于限制关键字参数的名字,比如说,下面的'city', 'job', 如果2个关键字参数少一个都会报错,同时也可以提供默认值,使用方式有几种

1.在命名关键字参数前添加一个*作为特殊参数分割符

def person(name, age, *, city, job):
  print(name, age, city, job)

>>> person('Louis', 28, city='Beijing')
> TypeError: person() missing 1 required keyword-only argument: 'job'

2.如果使用了可变参数,则可变参数后面的参数为命名关键字参数

# 可变参数*args后面的 city, job为命名关键字参数
def person(name, age, *args, city, job)
  print(name, age, args, city, job)

>>> person('james', 19, 'beijng', city='wuhan', job='worker')
james 19 ('beijng',) wuhan worker

# 缺少命名关键字参数则会报错
>>>  person('james', 19, 'beijng')
TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'

参数组合

python中定义函数,可以使用必选参数,默认参数,可变参数,关键字参数,命名关键字参数,但是要注意这5种参数的顺序是:可变参数,默认参数,可变参数,命名关键字参数, 关键字参数

示例:

# a,b必选参数, c默认参数,*args可变参数, **kw 关键字参数
def f1(a, b, c=0, *args, **kw):
  print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

# a,b必选参数, c默认参数,d命名关键字参数, **kw 关键字参数
def f2(a, b, c=0, *, d, **kw):
  print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

# 使用fun(*args, **kw)的形式
>>> args = (1, 2, 3, 4)  
>>> kw = {'d': 99, 'x': '#'}
>>> f1(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}


>>> args = (1, 2, 3)
>>> kw = {'d': 88, 'x': '#'}
>>> f2(*args, **kw)
a = 1 b = 2, c = 3 d = 88 kw = {'x': '#'}

*对于任意函数,都可以通过类似func(args, kw)的形式去调用它

三.引入模块

这一点和js中的import很像,假如当前路径下有个文件名叫 'hello.py', 这个文件里面有个函数叫 'my_abs',可以在其它模块中引用这个函数

from hello import my_abs

引入语言自带的一些库函数可以直接使用improt

import math

另外在terminal中可以使用下列命令查看文件的内容

more hello.py

四.返回多个值

这个其实是语法糖,本质上返回的是 tuple 数据类型,省略括号之后就看起来像返回多个值

import math

def move(x, y, step, angle=0):
  nx = x + step * math.cos(angle)
  ny = y + step * math.sin(angle)
  return nx, ny

>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print(x, y)
151.96152422706632, 70.0

# 可以写为
>>> t = move(100, 100, 60, math.pi / 6)
>>> print(t)
(151.96152422706632, 70.0)
# 可以看出返回的实际上是一个tuple

五.递归函数

递归函数就是函数自调用,使用尾部调用的方式可以优化递归调用,这点和其它语言一样。

尾部调用就是函数返回的时候,调用自身本身,并且return语句不能包含表达式

# 没有进行尾部调用优化
def fact(n):
  if n == 1:
    return 1
  return n * fact(n - 1)  # return后面有表达式

# 尾部调用优化

def fact(n):
  return fact_iter(n, 1)

def fact_iter(num, product):
  if num == 1:
    return product
  return fact_iter(num - 1, num * product)  

六.参数检查 raise

可以使用 raise 语句返回错误类型,相当于js中的throw,抛出错误

def my_abs:
  if not isinstance(x, (int, float)):
    raise TypeError('bad operand type')
  if x >= 0:
    return x
  else:
    return -x

另外可以看到:

  • isinstance: 这个用于判断数据类型,和js中的instanceOf类似

总结

本章主要介绍python中的函数,函数的定义形式,函数参数的几种类型,以及其它的一些知识:

  • 使用 def 来定义函数
  • pass 语句, raise 语句(相当于js中的throw,抛出错误), is 关键词, isinstance() 方法(用于检查对象类型)
  • 函数参数类型:必选参数,默认参数,任意参数,命名关键字参数, 关键字参数
  • import 引入模块,from xxx import some_fun 引入某个文件中的某个函数模块

总的来说,python中的函数参数定义和其它语言差别不是很大,最主要的不同在于命名关键字参数,关键字参数

2017年3月4日 17:31:46

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容