函数是可以重复执行的语句块
可以重复使用,提高代码的重用性, 定义用户级别的函数
def 函数名(参数列表):
语句块(也叫代码块)
1、函数的名字是语句块的名称
2、函数名必须是标识符(和变量的命名规则相同)
3、函数名是一个变量(不要轻易对其赋值),函数与变量一样,需要先定义再调用
4、函数有自己的名字空间,要让函数处理外部数据,需要用参数对此函数传入一些数据
5、函数如果不需要传入参数,则参数列表可以为空
6、语句部分不能为空,如果为空则需要填充pass语句
# 定义了一个叫myfun的函数
def myfun(): #(def需要顶格写)
print("hello world!")
# 调用myfun函数
myfun()
hello world!
def f1(): # 相当与创建函数再绑定变量
pass
f1() # 正确的调用
# ----------------------
f2() # 错误的调用,因为此时f2变量还没有绑定函数
def f2():
pass
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
in
4
5 # ----------------------
----> 6 f2() # 错误的调用,因为此时f2变量还没有绑定函数
7 def f2():
8 pass
TypeError: f2() missing 2 required keyword-only arguments: 'a' and 'b'
函数名(实际调用传递参数)
注:实际调用传递参数称为实参
练习:写一个函数,def mysum(a, b): ,调用时传入两个数,把两数之和打印出来
def mysum(a, b):
print("a的值是:", a)
print("b的值是:", b)
print("两个数的和值:", a + b)
mysum(2, 5)
a的值是: 2
b的值是: 5
两个数的和值: 7
函数名即变量,此变量在创建时绑定一个函数
def fn():
print("hello world!")
f1 = fn # 这里没有括号,相当于给fn绑定的这个函数起了一个别名
f1() # 调用函数fn
fn() # 调用函数fn
hello world!
hello world!
return [表达式]
注:[] 代表可以省略
用于函数中,结束当前函数的执行,返回到调用该函数的地方,同时返回一个值对象的引用关系
1、return 语句后跟的表达式可以省略,省略后相当于return None
2、如果函数内没有return语句,则函数执行完最后一条语句后返回None,相当于在最后加了一条return None语句
3、函数的调用能够用return 语句返回一个对象的引用
练习: 写一个函数mymax,实现返回两个数的最大值
def mymax2(a, b):
return a if a > b else b
print(mymax2(100, 200))
200
练习: 假设有一个列表有很多数据,还有重复的,打印出列表中的数据,要求重复的只打印一次,打印的顺序要以列表中第一次出现的顺序为准
L = [1, 1, 2, 3, 4, 8, 6, 6, 5, 4, 3]
def remove_duplicates_1(L):
l1 = []
s = set()
for x in L:
if x in s:
continue
s.add(x)
l1.append(x)
return l1
print(remove_duplicates_1(L))
def remove_duplicates_2(L):
s = set(L)
l1 = []
for x in L:
if x in s:
s.remove(x)
l1.append(x)
return l1
print(remove_duplicates_2(L))
def remove_duplicates_3(L):
l1 = []
for x in L:
if x not in l1:
l1.append(x)
return l1
print(remove_duplicates_3(L))
[1, 2, 3, 4, 8, 6, 5]
[1, 2, 3, 4, 8, 6, 5]
[1, 2, 3, 4, 8, 6, 5]
练习: 定义两个函数:sum3(a, b, c)用于返回三个数的和,pow(x) 用于返回x的三次方(立方
(1)、用以上函数计算 1 的三次方加 2 的三次方加 3 的三次方的和
(2)、计算1+2+3的立方
def sum3(a, b, c):
return (a + b + c)
def pow(x):
return x ** 3
print(sum3(pow(1), pow(2), pow(3)))
print(pow(sum3(1, 2, 3)))
36
216
位置传参
序列传参
关键字传参
字典关键字传参
实际参数(实参)的对应关系与形式参数(形参)对应关系是按位置依次对应的实参的个数和形参的个数要严格一致
def myfun1(a, b, c): # 形参
print(a)
print(b)
print(c)
# 调用
myfun1(1, 2, 3) # 实参
1
2
3
序列传参是指在函数调用过程中,用*将序列拆解后按位置进行传递的方式
序列传参时,序列拆解的位置将与形参一一对应
序列的位置信息对应相应的参数
L1 = [11,22,33]
T1 = (4.4,5.5,6.6)
S1 = "ABC"
myfun1(*L1)
myfun1(*T1)
myfun1(*S1)
11
22
33
4.4
5.5
6.6
A
B
C
关键字传参是指传参时,按形参的名称给形参赋值
实参和形参按形参名进行匹配(可以不按位置顺序进行匹配)
# 关键字传参
myfun1(c = 33, b = 22, a = 11)
11
22
33
是指实参为字典,将字典用**拆解后进行关键字传参
字典的键名和形参名必须一致
字典的键名必须为字符串,并符合关键字的命名
字典的键名要在形参中存在
d1 = {"c":33, "b":22, "a":11}
myfun1(**d1)
11
22
33
在能确定每个形参否能唯一匹配一个实参的情况也可以任意传参
传参时,位置传参和序列传参要先于关键字传参和字典关键子传参
myfun1(100, *[200, 300])
myfun1(*[10,20],30)
myfun1(*[10], 20, *[30])
myfun1(100, **{"c":300, "b":200})
myfun1(**{"c":300, "b":200}, a = 100)
100
200
300
10
20
30
10
20
30
100
200
300
100
200
300
myfun1(b = 200, c = 300, 100) # 错的
File "", line 1
myfun1(b = 200, c = 300, 100) # 错的
^
SyntaxError: positional argument follows keyword argument
1、不可变类型的数据作为函数参数传入时,函数内部不会改变变量的原数据的值
2、可变类型的数据作为函数参数传递时,函数内部可以改变原数据,多用与返回更多函数执行结果
练习:写一个函数:def mymin(x, y, z): 这个函数传入三个参数,返回三个中最小值,尝试使用四种传参方式?
def mymin(a, b, c):
t = a
if t > b:
t = b
if t > c:
t = c
return t
print(mymin(1, 2, 3))
print(mymin(*[1, 2, 3]))
print(mymin(a=1, b=2, c=3))
print(mymin(**{'a': 1, 'b': 2, 'c': 3}))
1
1
1
1
L = []
def fn(x):
# 创建一个局部变量,但不会修改全局的L变量
L = [x]
print(L, id(L))
def fn2(l):
# 全局的L变量已经改变
l.append(1)
print(l, id(l))
print(L, id(L))
fn(10)
print(L, id(L))
fn2(L)
print(L, id(L))
[] 4389963400
[10] 4389737928
[] 4389963400
[1] 4389963400
[1] 4389963400
练习: 写一个函数,在函数内输入一些整数,把所有奇数放入全局列表odds中, 把所有的偶数放入全局的列表evens中
odds = []
evens = []
def input_number(o, e):
while True:
n = int(input("请输入整数:"))
if n < 0:
break
# 如果n为奇数则添加列表odds中
if n % 2 == 1:
o.append(n)
else: # 如果n为偶数则添加到列表evens中
e.append(n)
input_number(odds, evens)
print(odds) # 此列表将被修改
print(evens) # 此列表也将被修改
请输入整数:5
请输入整数:8
请输入整数:1
请输入整数:-1
[5, 1]
[8]
位置形参
星号元组形参
命名关键字形参
双星号字典形参
def 函数名(形参名1, 形参名2, 形参名3,......):
语句块
def 函数名(*元组形参名):
语句块
def funs(*args):
# args绑定一个元组,此元组内的元素是为了剩余的位置传参
print("实参个数是:", len(args))
print("args绑定", args)
funs() # 以无参调用
funs(1, 2, 3, 4)
funs("ABC", 1, 2.3, 4+5J)
实参个数是: 0
args绑定 ()
实参个数是: 4
args绑定 (1, 2, 3, 4)
实参个数是: 4
args绑定 ('ABC', 1, 2.3, (4+5j))
练习:写一个函数mysum2,实参可以传入任意个,返回所有实参的和
def mysum2(*args):
s = 0
for x in args:
s += x
return s
print(mysum2(1, 2, 3, 4))
print(mysum2(1, 2.2, 3+4J))
10
(6.2+4j)
所有的命名关键字形参,必须用关键字传参或字典关键字传参进行参数传递
def 函数名(*, 命名关键字形参): # 不允许传位置参数
语句块
或:
def 函数名(*args, 命名关键字形参):
语句块
def fn(*, a, b):
print("a的值为:", a)
print("b的值为:", b)
# fn(1, 2) # 错的,a和b 必须是用关键字传参
fn(a = 1, b = 2) #必须这么传
fn(b = 0, a = 20)
fn(**{"b":200, "a":100})
def f2(*args, a, b):
print("args=", args)
print("a=", a)
print("b=", b)
f2(1, 2, 3, 4, a=100, b=200)
f2(a=100, b=200)
a的值为: 1
b的值为: 2
a的值为: 20
b的值为: 0
a的值为: 100
b的值为: 200
args= (1, 2, 3, 4)
a= 100
b= 200
args= ()
a= 100
b= 200
作用:收集多余的关键字传参(例如:dict()),通常只有一个
def 函数名(**字典形参名):
语句块
def func(**kwagrs): # kwagrs绑定一个字典
print("参数个数:", len(kwagrs))
print("kwagrs的值为:", kwagrs)
func(name="zhuang", age=25, address="dgas")
func(**{"name": "zhuang", "age": 25, "address": "dgas"})
func()
参数个数: 3
kwagrs的值为: {'name': 'zhuang', 'age': 25, 'address': 'dgas'}
参数个数: 3
kwagrs的值为: {'name': 'zhuang', 'age': 25, 'address': 'dgas'}
参数个数: 0
kwagrs的值为: {}
def 函数名(形参名1 = 默认实参1, 形参名2 = 默认实参2, ....):
语句块
说明:
1. 缺省参数必须自右至左依次存在,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数, 如:
def test_fn(a, b = 10, c): # 是错的
2. 缺省参数可以有0个或多个,甚至全部都有缺省参数
3. 位置形参和命名关键字形参可以使用缺省参数
def info(name, age=1, address="未填写"):
print(name, "住在:", address, "今年:", age, "岁")
info("庄AC", 23, "北京")
info("庄AC", 23)
庄AC 住在: 北京 今年: 23 岁
庄AC 住在: 未填写 今年: 23 岁
练习:写一个函数myadd有三个参数,此函数可以计算两个数的和,也可以计算三个数的和
def myadd(a, b, c=0):
return a + b + c
print(myadd(10, 20))
print(myadd(10, 20, 30))
30
60
位置形参, 星号元组形参, 命名关键字形参, 双星号字典形参
def fn(a, b="b", *args, c, f="f", **kwargs):
print(a, b, args, c, f, kwargs)
fn(100,200,300,400,c=5.5,d=6.6,e=7.7, f=8.8)
fn(10,*"AB",20,**{"d": 11, "e": 33, "c":300})
# ----------以下函数可以接受任意的位置传参和关键字传参------------
def fn(*args, **kwargs):
pass
100 200 (300, 400) 5.5 8.8 {'d': 6.6, 'e': 7.7}
10 A ('B', 20) 300 f {'d': 11, 'e': 33}
def 函数名(形参列表)
函数文档字符串
语句块
1、函数的定义语句(def 语句)的第一次出现的没有赋值给任何变量的字符串为文档字符串
2、文档字符串通常用来说明本函数的功能和使用方法
3、在交互模式下,输入>>>help(函数名) 可以查看文档字符串
def myfun():
"""我是文档字符串"""
help(myfun)
Help on function myfun in module __main__:
myfun()
我是文档字符串
只能用在python3.5 之后的版本
def fn(a:"第一个参数", b:"第二个参数", c:int) -> str:
return str(a + b + c)
fn(1, 2, 3)
'6'
详见:>>> help(“def”)
[装饰器]
def 函数名([位置形参], [*元组形参], [命名关键字形参], [**字典形参]) [-> 注释表达式]:
"""文档字符串"""
语句块
help("def")
作用:用来记录函数名
说明:1、通常属性是指对象(实例)的变量
2、以双下划线开头,以双下划线结尾的标识符代表Python的特殊变量
def abc():
pass
fn = abc
print("fn绑定的函数名是:", fn.__name__)
fn绑定的函数名是: abc
作用:用于记录文档字符串
def cba():
"这是一块文档字符串"
pass
print(cba.__doc__)
这是一块文档字符串
Python创造了一个新的函数对象。在这个函数对象里,可以看到字节码,元数(也就是参数数量)和一些与函数相关的其他东西。大多数这些东西存在于函数对象的__code__属性里。事实上,研究__code__是了解Python函数如何运行的最好办法。
def foo():
return "I'm foo!"
# 函数foo的元数是由foo.__code__.co_argcount获得,而字码节存在于foo.__code__.co_code中。
print(foo.__code__.co_argcount, foo.__code__.co_code)
def bar():
return "I'm bar!"
# __code__对象的属性是只读,但是__code__属性本身不是
foo.__code__ = bar.__code__
foo()
0 b'd\x01S\x00'
"I'm bar!"
练习:仿造max,写一个mymax函数,功能与max完全相同(要求,不允许调用max函数)
def mymax(a, *args):
if len(args) != 0:
m = a
for x in args:
if x > m:
m = x
else:
m = a[0]
for i in range(1, len(a)):
if a[i] > m:
m = a[i]
return m
print(mymax([6, 8, 3, 5]))
print(mymax(100, 200))
8
200
练习:写一个myrange函数,参数可以传入1-3个,实际含义同range函数规则相同, 此函数返回符合range(....) 函数规则的列表
如:
L = myrange(4) # L = [0, 1, 2, 3]
L = myrange(4, 6) # L = [4, 5]
L = myrange(1, 10, 3) # L = [1, 4, 7]
print(L) # [1, 4, 7]
def myrange(*args, x=1):
L = []
if len(args) == 1:
i = 0
while i < args[0]:
L.append(i)
i += x
elif len(args) == 2:
if args[0] > args[1]:
return L
i = args[0]
while i < args[1]:
L.append(i)
i += x
elif len(args) == 3:
i = args[0]
x = args[2]
while i < args[1]:
L.append(i)
i += x
else:
return ("TypeError: range expected at most 3 arguments")
return L
print(myrange(5))
print(myrange(2, 6))
print(myrange(5, 10, 2))
print(myrange(5, 5))
[0, 1, 2, 3, 4]
[2, 3, 4, 5]
[5, 7, 9]
[]
练习: 写一个函数isprime(x),判断x是否为素数,如果为素数返回True,否则返回False
def isprime(x):
if x <= 1:
return False
for i in range(2, x):
if x % i == 0:
return False
return True
isprime(3)
True
练习: 写一个函数prime_m2n(m, n)返回从m开始,到n结束内所有的素数的列表
def primes(start, stop):
L = []
for a in range(start, stop):
if isprime(a):
L.append(a)
print(L)
primes(100, 200)
[101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]
同名公众号:庄AC