python3精简笔记(二)——函数

简介: 函数下面的地址可以查看函数: https://docs.python.org/3/library/functions.html也可以在交互式命令行通过help()查看函数的帮助信息。 如:>>>help(abs)调用函数也非常简单,传入的参数数量和类型一致就行,传入的参数数量不对或类型不能被函数所接受,会报TypeError的错误

函数

下面的地址可以查看函数:
https://docs.python.org/3/library/functions.html

也可以在交互式命令行通过help()查看函数的帮助信息。
如:

>>>help(abs)

调用函数也非常简单,传入的参数数量和类型一致就行,传入的参数数量不对或类型不能被函数所接受,会报TypeError的错误

>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34

函数max()可以接收任意多个参数,并返回最大的那个:

>>> max(1, 2)
2
>>> max(2, 3, 1, -5)
3

类型转换函数

Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:

>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> str(100)
'100'
>>> bool(1)
True
>>> bool('')
False

把函数名赋给一个变量,相当于给这个函数起了一个“别名”:

>>> a = abs # 变量a指向abs函数
>>> a(-1) # 所以也可以通过a调用abs函数
1

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

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

空函数

如果想定义一个什么事也不做的空函数,可以用pass语句:

def nop():
pass

pass语句什么都不做,那有什么用?

实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

pass还可以用在其他语句里,比如:

if age >= 18:
pass

缺少了pass,代码运行就会有语法错误。

定义错误处理

当传入了不恰当的参数时,内置函数abs会检查出参数错误,而我们定义的my_abs没有参数检查,会导致if语句出错,出错信息和abs不一样。
如:

>>> my_abs('A')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in my_abs
TypeError: unorderable types: str() >= int()
>>> abs('A')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bad operand type for abs(): 'str'

修改一下my_abs的定义,对参数类型做检查,只允许整数和浮点数类型的参数。数据类型检查可以用内置函数isinstance()实现:

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

返回多个值

比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的新的坐标:

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);

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

综合案例:

定义一个函数quadratic(a, b, c),接收3个参数,返回一元二次方程:

ax2 + bx + c = 0

的两个解。

公式:

x=(-b±√(b^2-4ac))/2a

a为0的时候只有一个解,b^2-4ac<0的时候无解。

import math

def quadratic(a, b, c):
if(a==0 and b==0):
return;
delta=b*b-4*a*c
if(delta<0):
print("此方程无解")
return;
elif(a==0 and b!=0):
return -c/b
else:
return (-b+math.sqrt(delta))/2*a,(-b-math.sqrt(delta))/2*a

a=input("输入a");
b=input("输入b");
c=input("输入c");

r=quadratic(int(a), int(b), int(c));
print(r);

默认参数

Python定义函数的时候,可以指定参数默认的值,这时候可以不传该参数

例: 我们经常计算x2,所以,完全可以把第二个参数n的默认值设定为2,比Java的重载方法要简单。

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

当我们调用power(5)时,相当于调用power(5, 2)

注意
* 一是必选参数在前,默认参数在后
* 当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。
* 默认参数要牢记一点:默认参数必须指向不变对象!L=[]这种就有可能有问题

下面定义了一个函数

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

观察下, 如果age和city分别为空的时候,如何输入

enroll('Bob', 'M', 7)
#可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。
enroll('Adam', 'M', city='Tianjin')

可变参数

在Python函数中,还可以定义可变参数。

定义可变参数和定义一个listtuple参数相比,仅仅在参数前面加了一个*号。参数numbers接收到的是一个tuple

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

如果已经有一个list或者tuple,要调用一个可变参数怎么办?

>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2])
14

这种写法当然是可行的,问题是太繁琐,所以Python允许你在listtuple前面加一个*号,把listtuple的元素变成可变参数传进去:

>>> nums = [1, 2, 3]
>>> calc(*nums)
14

*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。

关键字参数

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

使用**控制

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

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

>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

**extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dictextra的一份拷贝,对kw的改动不会影响到函数外的extra

命名关键字参数

对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。

def person(name, age, **kw):
if 'city' in kw:
# 有city参数
pass
if 'job' in kw:
# 有job参数
pass
print('name:', name, 'age:', age, 'other:', kw)

但是调用者仍可以传入不受限制的关键字参数:

>>> person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)

果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收cityjob作为关键字参数。这种方式定义的函数如下:

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

和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数。

调用方式如下:

>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer

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

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

命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。

命名关键字参数可以有缺省值,从而简化调用:

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

由于命名关键字参数city具有默认值,调用时,可不传入city参数:

>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer

关键字参数

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

使用**控制

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

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

>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

**extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dictextra的一份拷贝,对kw的改动不会影响到函数外的extra

命名关键字参数

对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。

def person(name, age, **kw):
if 'city' in kw:
# 有city参数
pass
if 'job' in kw:
# 有job参数
pass
print('name:', name, 'age:', age, 'other:', kw)

但是调用者仍可以传入不受限制的关键字参数:

>>> person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)

果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收cityjob作为关键字参数。这种方式定义的函数如下:

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

和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数。

调用方式如下:

>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer

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

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

命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。

命名关键字参数可以有缺省值,从而简化调用:

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

由于命名关键字参数city具有默认值,调用时,可不传入city参数:

>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer

参数组合

Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这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)

在函数调用的时候,Python解释器自动按照参数位置和参数名把对应的参数传进去。

>>> 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,你也可以调用上述函数:

>>> 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)的形式调用它,无论它的参数是如何定义的。


更多精彩请关注微信公众账号likeDev
这里写图片描述

相关文章
|
29天前
|
Python
【python从入门到精通】-- 第五战:函数大总结
【python从入门到精通】-- 第五战:函数大总结
62 0
|
26天前
|
Python
Python之函数详解
【10月更文挑战第12天】
Python之函数详解
|
27天前
|
存储 数据安全/隐私保护 索引
|
16天前
|
测试技术 数据安全/隐私保护 Python
探索Python中的装饰器:简化和增强你的函数
【10月更文挑战第24天】在Python编程的海洋中,装饰器是那把可以令你的代码更简洁、更强大的魔法棒。它们不仅能够扩展函数的功能,还能保持代码的整洁性。本文将带你深入了解装饰器的概念、实现方式以及如何通过它们来提升你的代码质量。让我们一起揭开装饰器的神秘面纱,学习如何用它们来打造更加优雅和高效的代码。
|
18天前
|
弹性计算 安全 数据处理
Python高手秘籍:列表推导式与Lambda函数的高效应用
列表推导式和Lambda函数是Python中强大的工具。列表推导式允许在一行代码中生成新列表,而Lambda函数则是用于简单操作的匿名函数。通过示例展示了如何使用这些工具进行数据处理和功能实现,包括生成偶数平方、展平二维列表、按长度排序单词等。这些工具在Python编程中具有高度的灵活性和实用性。
|
21天前
|
Python
python的时间操作time-函数介绍
【10月更文挑战第19天】 python模块time的函数使用介绍和使用。
26 4
|
22天前
|
存储 Python
[oeasy]python038_ range函数_大小写字母的起止范围_start_stop
本文介绍了Python中`range`函数的使用方法及其在生成大小写字母序号范围时的应用。通过示例展示了如何利用`range`和`for`循环输出指定范围内的数字,重点讲解了小写和大写字母对应的ASCII码值范围,并解释了`range`函数的参数(start, stop)以及为何不包括stop值的原因。最后,文章留下了关于为何`range`不包含stop值的问题,留待下一次讨论。
17 1
|
28天前
|
索引 Python
Python中的其他内置函数有哪些
【10月更文挑战第12天】Python中的其他内置函数有哪些
15 1
|
1月前
|
搜索推荐 Python
Leecode 101刷题笔记之第五章:和你一起你轻松刷题(Python)
这篇文章是关于LeetCode第101章的刷题笔记,涵盖了多种排序算法的Python实现和两个中等难度的编程练习题的解法。
19 3
|
1月前
|
存储 开发工具 Python
【Python项目】外星人入侵项目笔记
【Python项目】外星人入侵项目笔记
36 3