0%

Python3 入门之函数基础

函数基础

函数是最基本的一种代码抽象方式

条件判断

根据 Python 的缩进规则,如果 if 语句判断为 True ,就把接下来缩进的语句执行,否则执行 else 的内容

1
2
3
4
5
6
7
>>> age = 20
>>> if age>= 18:
... print("your age is",age)
... else:
... print("haha child")
...
your age is 20

注意不要漏了 : ,也可以使用 elif 来表示 else if

1
2
3
4
5
6
7
8
if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>

if 语句是从上向下判断的,如果在某个判断上为 True,则把对应语句执行后就忽略掉剩下的语句。

if 语句可以简写如下:

1
2
if x:
print('True')

只要 x 是非零数值、非空字符串、非空list等,就判断为 True,否则为 False

再看 input

我们使用 input() 来获取用户的输入,比如以下程序段:

1
2
3
4
5
birth = input('birth: ')
if birth < 2000:
print('00前')
else:
print('00后')

输入 1982abc 均会报错,这是为什么呢?

原来 input() 返回的数据类型是 str ,它是不能直接和整数相比较的,我们必须把它进行转换。 使用 int() 可以转换 1982 为整数;而 abc 则需要进行数据类型的合法检查,它是不能转换成整数的。

循环

Python 的循环有两种,一种是 for ... in 循环,一种是 while 循环

for 循环

for 循环依次把 list 或 tuple 中的每个元素迭代出来

1
2
3
4
5
6
7
>>> names = ['jack','tom','rose']
>>> for name in names:
... print(name)
...
jack
tom
rose

Python 提供了一个 range() 函数,再通过 list() 函数可以将其转换为 list。比如 range(101) 就是生存从 0 开始小于 101 的整数序列。

1
2
3
4
5
6
>>> sum = 0
>>> for x in range(101):
... sum = sum + x
...
>>> print(sum)
5050

while 循环

while 循环是只要条件满足,就不断循环;条件不满足时,退出循环

1
2
3
4
5
6
7
8
>>> sum = 0
>>> n = 100
>>> while n > 0:
... sum = sum + n
... n = n - 1
...
>>> print(sum)
5050

break

在循环中,break 语句可以提前退出循环

continue 语句可以跳过这次循环,直接开始下一次循环

函数调用

Python 内置了很多函数,可以直接调用。调用函数需要知道函数名及函数参数,可参考 官方文档

当调用函数出错时,系统会给出相应的错误信息,查看信息即可知道原因并进行修改

max 函数

max() 函数可以接收多个参数,并输出其中最大的那个

1
2
>>> max(2,0,-5,8)
8

数据类型转换函数

1
2
3
4
5
6
7
8
9
10
11
12
>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> bool(1)
True
>>> bool('')
False

函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个「别名」:

1
2
3
>>> a = int
>>> a('123')
123

函数定义

在 Python 中定义一个函数需要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号,在缩进块中编写函数体,函数的返回值使用 return 返回。

1
2
3
4
5
6
7
def isGood(x):
if x>=60:
return True
else :
return False

print(isGood(89))

函数体内部一旦执行到 return 时,函数就执行完毕,并将结果返回。如果没有 return 语句,函数执行完毕后也会返回结果,只不过结果是 None 。return None 可以简写为 return

空函数

如果想定义一个空函数,什么也不干,那么可以使用 pass 语句;实际上 pass 语句可以用来做占位符,比如现在没有想好该怎么做,就可以先使用 pass 语句让代码跑起来。

1
2
def nop():
pass

pass 语句还可以放在其它语句里,比如:

1
2
if age >= 18:
pass

如果缺少 pass,则程序会报错

参数检查

调用参数时,如果参数个数不对,Python 解释器会自动检查出来并抛出错误 TypeError

我们可以给自己的函数加上参数类型检测,使用 isinstance() 内置函数方法。如下是只允许整数和浮点数类型的参数:

1
2
3
4
5
6
7
8
9
def isGood(x):
if not isinstance(x,(int,float)):
raise TypeError('bad operation type')
if x>=60 :
return True
else :
return False

print(isGood(89))

返回多个值

函数是可以返回多个值的。比如游戏中从其中一个点移动到另一个点,给出坐标、位移、角度,可以计算出新的坐标:

1
2
3
4
5
6
import math

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

我们可以同时获得返回值

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

但是这只是一个假象,Python 函数返回的仍是单一值:

1
2
3
>>> r = move(100, 100, 60, math.pi / 6)
>>> print(r)
(151.96152422706632, 70.0)

原来返回的是一个 tuple !在语法上,返回一个 tuple 可以省略括号,而多个变量可以同时接收一个 tuple,按位置给对应的值。所以,Python 的函数返回多个值其实就是返回一个 tuple。

函数的参数

Python 的函数定义非常简单,灵活度很大,除了必须的参数外,还有默认参数、可变参数和关键字参数

位置参数
1
2
def power(x):
return x * x

对于该函数来说,x 就是一个位置参数;当我们对函数进行改造以便生成 x 的 n 次方:

1
2
3
4
5
6
def power(x,n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s

修改后的函数有两个参数,两个都是位置参数,调用函数时,传入的值按照位置顺序依次赋给参数。

默认参数

新建的函数 power(x,n) 调用没有问题,但是原有的一个参数的函数调用出问题了,系统告诉我们是因为缺少一个位置参数。因此,我们可以将第二个参数的默认值设置为 n = 2 :

1
2
3
4
5
6
def power(x,n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s

这样,当我们调用 power(5) 时,实际就是调用 power(5,2)。而对于其它 n>2 的情况下,则必须明确的传入参数值。

注意:

  • 必选参数在前,默认参数在后
  • 变化大的参数放在前面,变化小的参数放在后面;变化小的参数可以作为默认参数
  • 默认参数降低了函数调用的难度
  • 当有多个默认参数时,既可以按顺序提供默认参数,也可以不按顺序提供默认参数
  • 当不按顺序提供默认参数时,必须要把参数名写上
  • 默认参数必须指向不变对象
可变参数

Python 中,可以定义可变参数。可变参数就是参数的个数是可变的,可以是 1 个,2 个到任意个,也可以是 0 个。

1
2
3
4
5
def calc(*numbers)
sum = 0
for n in numbers:
sum = sum + n * n
return sum

定义一个可变参数和定义一个 list 或 tuple 相比,仅仅在参数前多了一个 * 号。 *numbers 表示把 numbers 这个 list 的所有元素作为可变参数传进去。

关键字参数

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

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

可以传入任意个数的关键字参数:

1
2
3
4
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

这种函数可以扩展函数功能,除了保证能接收到必要参数,对于调用者额外提供的参数也能获取到。

和可变参数一样,我们也可以先组装出一个 dict,然后把该 dict 转换为关键字参数传进去。

命名关键字参数

对于关键字参数,函数调用者可以传入任意不受限制的关键字参数。对于传入参数的判断,只能在 kw 内部进行检查。以上面的 person() 函数为例,当我们只想调用者传入 city 和 job 做为关键字参数时,我们就可以使用「命名关键字参数」。这种函数的定义如下:

1
2
def person(name,age,*,city,job)
print(name,age,city,job)

和关键字参数不一样的地方就是命名关键字参数需要使用分隔符 ** 后面的参数被视为命名关键字参数。

如果函数定义中已经有了一个可变参数,那么后面跟着的命名关键字参数就不再需要 * 分隔符了。

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

命名关键字参数和位置参数不同,它必须要传入参数名,否则将报错。命名关键字参数可以有缺省值,类似默认参数。

1
2
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)

使用命名关键字参数时,要特别注意,如果没有可变参数,就必须加一个 * 作为特殊分隔符。如果缺少 * ,Python 解释器将无法识别位置参数和命名关键字参数:

1
2
3
def person(name, age, city, job):
# 缺少 *,city和job被视为位置参数
pass
参数组合

在 Python 中定义函数,可以使用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这五种参数都可以组合使用。但是,参数的定义顺序必须是:***必选参数、默认参数、可变参数、命名关键字参数和关键字参数***

1
2
3
4
5
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

调用结果如下:

1
2
3
4
5
6
7
8
9
10
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

通过一个 tuple 和 dict ,也可以调用上述函数:

1
2
3
4
5
6
7
8
>>> 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) 的形式进行调用,而不管它的参数是如何定义的。

小结

Python 的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。

默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!

要注意定义可变参数和关键字参数的语法:

  • *args 是可变参数,args 接收的是一个 tuple;
  • **kw 是关键字参数,kw 接收的是一个 dict。

以及调用函数时如何传入可变参数和关键字参数的语法:

可变参数既可以直接传入:func(1, 2, 3),又可以先组装 list 或 tuple,再通过 *args 传入:func(*(1, 2, 3));

关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过 **kw 传入:func(**{‘a’: 1, ‘b’: 2})。

使用 *args**kw 是 Python 的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。

命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。

定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符*,否则定义的将是位置参数。