python函数
1.函数的基本概念
-
不使用函数,代码缺点:冗余,可读性很差,维护性太差
-
函数:把多行代码封装成一个整体,在使用时直接调用。
-
在Python里,使用关键字def来声明一个函数
-
def 函数名(参数):
函数要执行的操作
-
函数名也是一个标识符,由数字、字母或下划线组成,不能以数字开头,严格区分大小写;不能使用关键字
-
遵守命名规范,使用下划线连接;顾名思义
-
函数定义好了以后并不会自动执行,需要主动调用
-
定义函数时传递的参数叫做形参,形参的值是不确定的,只是用来占位的
-
函数调用时传入的参数,才是真正参与运算的数据,我们称之为实参
def tell_story(place, person1, person2): # place,person1,person2是形式参数
print("从前有座山")
print("山里有座%s" % place)
print("%s里有个%s" % (place, person1))
print("还有一个%s" % person2)
print("%s在%s讲故事" % (person1, person2))
print("故事的内容是:")
age = int(input('请输入孩子的年龄:\n'))
if 0 <= age <= 3:
for i in range(5):
tell_story('尼姑庵', '师太', '小尼姑') # 调用函数时传的参数是实参
elif 3 < age <= 5:
tell_story('道观', '老道', '童子') # 会把实参一一对应的传递,交给形参处理
else:
print("别用这个故事忽悠了,换个花样吧")
# 还可以通过定义变量名的形式给形参赋值
tell_story(person2='青年', person1='禅师', place='武当山')
2. 函数的返回值
- 函数的返回值就是函数执行的结果,并不是所有的函数都必须要有返回值;
def add(a, b):
c = a + b # 变量C在外部是不可见的,只能在函数内部使用
return c # return 表示一个函数的执行结果
# 获取到 add 函数的结果,然后再求结果的 4 次方
result = add(1,2)
print(result**4)
# 如果一个函数没有返回值,它的返回就是None
# print就是一个内置函数
x = print('hello') # None
age = input('请输入您的年龄:')
print(age)
3. 函数的注释
def add(a:int, b:int): # :int 只是一个建议
"""
这个函数用来将两个数字相加
:param a: 第一个数字
:param b: 第二个数字
:return: 两个数字相加的结果
"""
return a + b
# help(add) # 查看函数的详情
x = add(1, 2)
print(x)
y = add('hello', 'world')
print(y)
z = add('hello', 5)
print(z)
4. 函数调用函数
- 在一个函数内部调用了另外一个函数
def test1():
print("test1开始了")
print("test1结束了")
def test2():
print("test2开始了")
test1()
print("test2结束了")
# 定义函数求n~m之间所有整数之和
def sumInt(m, n):
su = 0
for i in range(m, n + 1):
su += i
return su
# 求一个n的阶乘
def factor(n):
x = 1
for i in range(1, n + 1):
x *= i
return x
def sumFac(m):
sumf = 0
for i in range(1, m + 1):
sumf += factor(i)
return sumf
# 计算m阶乘的和 m = 6 ==> 1!+2!+3!+4!+5!+6!
def sumFactor(m):
sumf = 0
for i in range(1, m + 1):
x = 1
for j in range(1, i + 1):
x *= j
sumf += x
return sumf
# test2()
# s = sumInt(1, 10)
# print(s) # 55
# y = factor(5)
# print(y) # 120
# sf = sumFactor(6)
# print(sf) # 873
sf1 = sumFac(6)
print(sf1) # 873
5. 全局变量和局部变量
- 在函数外部定义的变量是全局变量,在整个py文件里都可以访问
- 在函数内部定义的变量,它是局部变量,只能在函数内部使用
- 如果局部变量的名和全局变量同名,会在函数内部又定义一个新的局部变量
- 内置函数 globals()可以查看全局变量 locals() 可以查看局部变量
- 在Python里,只有函数能够分割作用域
a = 100 # 这个变量是全局变量,在整个py文件里都可以访问
word = 'butiful'
def Test():
x = 'hello' # 在函数内部定义的变量,它是局部变量,只能在函数内部使用
print('x = {}'.format(x))
# print('函数内部 a = {}'.format(a))
# 如果局部变量的名和全局变量同名,会在函数内部又定义一个新的局部变量
a = 10 # 在函数内部又定义了一个新的局部变量
print('函数内部 a = {}'.format(a))
# 函数内部如果想要修改全部变量
global word
word = 'ok'
print('locals = {}, globals = {}'.format(locals(), globals()))
Test()
print('函数外部 a = {}'.format(a))
print('函数外部 word = {}'.format(word))
if 3 > 2:
m = 'test' # 条件成立时,m是全局变量,条件不成立,m未定义
print(m)
6. 函数多个返回值
- 函数返回多个结果,就是将多个数据打包成一个整体返回
- 可以使用列表和字典,通常情况下选择使用元组
def tst(a, b):
x = a // b
y = a % b
# 一般情况下,一个函数置灰执行一个return语句
# 特殊情况(finally语句)下,一个函数可能会执行多个return语句
# return x # return语句表示一个函数的结束
# return y
# return [x, y]
# return {'x': x, 'y': y}
# return (x, y)
return x, y # 返回的本质是一个元组
result = tst(12, 5)
print(result)
print('商是 {},余数是 {}'.format(result[0], result[1]))
quotient, remainder = tst(16, 3)
print('商是 {},余数是 {}'.format(quotient, remainder))
7. 默认参数的使用
- 默认参数也就是缺省参数:有些函数的参数值,如果你传递了参数,就是用传递的参数,如果没有传递参数,就使用默认的值
- 缺省参数要放在后面
# def say_hello(city='北京', name, age): # 缺省参数要放在后面
def say_hello(name, age, city='北京'):
print('大家好,我是{},我今年{}岁了,我来自{}'.format(name, age, city))
say_hello('李明', 18, '哈尔滨') # 直接传递的参数叫做位置参数
say_hello('刘星', 19)
say_hello(age=15, name='查理', city='南京') # 使用变量赋值传递的参数叫关键字参数
# 可以直接传递单个参数,也可以使用变量赋值的形式传参
# 如果有位置参数和关键字参数,关键字参数一定要放在位置参数的后面
say_hello('姚晨', age=15, city='南京') # 如果传递参数,就使用传递的实参
# say_hello(name='鲁滨逊', 21, city='成都') # 不能这样写
# print函数里end就是一个缺省参数
print('hello', '你好', sep='--', end='')
8. 可变参数的使用
- *args便是可变位置参数
- **kwargs表示可变的关键字参数
# *args 表示可变位置参数
# **kwargs 表示可变的关键字参数
def add(a, b, *args, mul=1, **kwargs): # 缺省参数要放在可变参数的后面
# print('a = {}, b = {}'.format(a, b))
# print('args = {}'.format(args)) # 多出来的可变参数会以元组的形式保存到args里
print('kwargs = {}'.format(kwargs)) # 多出来的关键字参数会以字典的形式保存
s = a + b
for arg in args:
s += arg
print(s + mul)
add(1, 3)
add(9, 5, 4, 2, 0)
add(1, 3, 5, 7, mul=2, x=0, y=4) # kwargs = {'x': 0, 'y': 4},18
9. 函数的注意事项
- 函数的三要素:函数名、参数和返回值
- 在有一些编程语言(java,c)里,允许函数重名,在Python里不允许函数的重名
- 如果函数重名了,后一个函数会覆盖前一个函数
- python里,函数名也可以理解成一个变量名
def test(a, b):
print('hello, a = {}, b = {}'.format(a, b))
def test(a):
print('good, a = {}'.format(a))
test(3, 4)
test = 5
test(3) # test 不再是一个函数,而是一个int变量,不能调用
10. 递归函数的使用
- 递归简单来说,就是函数内部自己调用自己
- 递归最重要的就是找到出口(停止的条件)
def test():
print('test')
test()
count = 0
def tell_story():
global count
count += 1
print("从前有座山")
print("山里有座庙")
print("庙里有个老和尚")
print("还有一个小和尚")
print("老和尚在小和尚讲故事")
print("故事的内容是")
if count < 5: # 设定递归停止的条件,5次以后停止
tell_story()
# 求 1 ~ n 的和
def get_sum(n):
if n == 0:
return 0
return get_sum(n-1) + n
# 使用递归求 n!
def get_factor(n):
if n == 0:
return 1
return get_factor(n-1) * n
# 使用递归求斐波那契数列的第 n 个数字 1,1,2,3,5,8,13,21,34,55,89,144,233……
def fibonacci(n):
if n == 1 or n == 2:
return 1
return fibonacci(n -1) + fibonacci(n - 2)
# tell_story()
# print(get_sum(5))
# print(get_factor(6)) # 720
print(fibonacci(6)) # 8
11. 匿名函数
-
除了使用def 关键字定义一个函数以外,还可以使用 lambda 表达式定义一个函数
-
lambda x, y: x * y
-
调用匿名函数两种方式:
-
给它定义一个名字(很少这样使用)
-
把这个函数当做参数传给另一个函数使用
-
def add(a, b):
return a + b
# x = add(4, 5) # 函数名(实参) 作用是调用函数,获取到函数的执行结果,并赋值给变量x
# print(x)
# print("0x%X" % id(add))
# fn = add # 相当于给函数add起了一个别名fn
# print("0x%X" % id(fn))
# print(fn(3, 4))
# lambda a, b: a * b # 匿名函数
def calc(a, b, fn):
c = fn(a, b)
return c
# def addi(a, b):
# return a + b
# def minus(a, b):
# return a - b
# x1 = calc(1, 2, addi) # a=1,b=2,fn=addi
# x2 = calc(10, 5, minus) # a=10,b=5,fn=minus
# print(x1, x2)
x3 = calc(5, 11, lambda x, y: x + y)
x4 = calc(16, 4, lambda x, y: x - y)
x5 = calc(4, 5, lambda x, y: x * y)
x6 = calc(12, 4, lambda x, y: x / y)
print(x3, x4, x5, x6)
12. 列表的sort方法和内置函数sorted
# 列表有几个内置函数和内置类,用了匿名函数
nums = [4, 8, 2, 1, 7, 6]
# nums.sort()
# print(nums)
tup = (5, 9, 2, 1, 3, 8, 7, 4)
# sorted内置函数,不会改变原有的数据,而是生成一个新的结果
# x = sorted(nums)
# print(x)
x1 = sorted(tup)
# print(x1) # [1, 2, 3, 4, 5, 7, 8, 9]
students = [
{'name': 'zhangsan', 'age': 18, 'score': 98, 'height': 180},
{'name': 'lisi', 'age': 21, 'score': 97, 'height': 185},
{'name': 'jone', 'age': 22, 'score': 100, 'height': 175},
{'name': 'tony', 'age': 23, 'score': 90, 'height': 176},
{'name': 'henry', 'age': 20, 'score': 95, 'height': 172}
]
# 字典和字典之间不能使用比较运算 <
# student.sort()
def foo(ele):
# print("ele = {}".format(ele))
return ele['height']
# 需要传递参数 key 指定比较规则
# key 参数类型是函数
# 在sort内部实现的时候,调用了foo方法,并且传入了一个参数,参数就是列表里的元素
# students.sort(key=foo)
students.sort(key = lambda ele: ele['score'])
print(students)
13. filter内置类、map和reduce
from functools import reduce
# filter 对可迭代对象进行过滤,得到的是一个filter对象,python2的时候是内置函数,python3修改成了一个内置类
# filter 可以给定两个参数,第一个参数是函数,第二个参数是可迭代对象
ages = [12, 23, 25, 30, 18, 22, 23, 30]
x = filter(lambda ele: ele > 18, ages)
# print(x)
# for i in x:
# print(i)
# adult = list(x)
# print(adult)
nums = [12, 23, 25, 30, 18, 22, 23, 30]
# m = map(lambda ele: ele + 2, nums)
# print(list(m)) # 把可迭代对象里的元素都执行函数里的动作
# reduce 以前是一个函数
# 内置函数和内置类都在 builtins.py文件里
# print(reduce(lambda ele1, ele2: ele1 + ele2, nums)) # 183
def foo(x, y): # x=12,y=23;x=35,y=25;x=60,y-30;
return x + y
# print(reduce(foo, nums)) # 183
students = [
{'name': 'zhangsan', 'age': 18, 'score': 98, 'height': 180},
{'name': 'lisi', 'age': 21, 'score': 97, 'height': 185},
{'name': 'jone', 'age': 22, 'score': 100, 'height': 175},
{'name': 'tony', 'age': 23, 'score': 90, 'height': 176},
{'name': 'henry', 'age': 20, 'score': 95, 'height': 172}
]
def bar(x, y):
return x + y['age'] # x = 0, y ={'name': 'zhangsan', 'age': 18, 'score': 98, 'height': 180}
# result = reduce(bar, students, 0) # 0 是初始值
# print(result)
r1 = reduce(lambda x, y:x + y['age'], students, 0)
print(r1) # 104,18+21+22+23+20
14. 内置函数的总结
# 1、abs 求绝对值
print(abs(-10), abs(5)) # 10, 5
# 2、all 把所有元素转换成布尔值,如果全是True,则返回True,否则返回False
print(all(['hello', 'world', 'everything'])) # True
print(all(['hello', 'world', 0])) # False
# 3、any 只要有一个元素转换成为布尔值是True,结果就是True
print(any(['hello', None, 0])) # True
# 4、ascii 把字符转换成ASCII码
print(ascii('a')) # 'a'
# 5、bin 将数字转换成为二级制
print(bin(1)) # 0b1
# 6、chr 将字符编码转换成为对应的字符
print(chr(97)) # 'a'
# 7、ord 将字符转换成对应的字符编码
print(ord('A')) # 65
# 8、dir 列出对象所有的属性和方法
# print(dir(list)) # [...'append', 'clear', 'copy', 'count', 'extend', 'index'... ]
# 9、divmod 求除法的商和余数
print(divmod(12, 5)) # (2, 2)
# 10、exit 以指定的退出码退出程序
# exit(200)
# 11、globals 用来查看所有的全局变量
a =1
print(globals())
# 12、locals 用来查看所有的局部变量
def foo():
b = 2
return b
print(locals())
# 13、help 用来查看帮助文档的
# help(list)
# 14、print 打印内容
# 15、input 让用户输入内容
# x = input('请输入')
# print(x)
# 16、isinstance 用来判断一个对象是否是由一个类创建出来的
# 17、issubclass 用来判断一个类是否是另一个类的子类
# 18、len 获取长度
# 19、iter 获取到可迭代对象的迭代器
# 20、next for...in循环本质就是调用迭代器的next方法
# 21、max 求最大数
# 22、min 求最小数
# 23、open 用来打开一个文件
# 24、pow 幂运算
# 25、round 四舍五入,保留到指定小数位
print(round(3.1415926, 2))
# 26、sum 用来求和
# 27、repr 把一个对象变成一个字符串
person = {'name': 'zhangsan'}
print(repr(person)) # "{'name': 'zhangsan'}"
15. 高阶函数
- 一个函数作为另一个函数的参数
- 一个函数作为另一个函数的返回值
- 函数内部再定义一个函数
def foo():
print('我是foo,我被调用了')
return 'foo'
def bar():
print('我是bar,我被调用了')
# return foo()
return foo
x = bar()
print(x)
y = bar()()
print(y) # 'foo'
def outer():
m = 100
def inner():
n = 90
print('我是inner函数')
print('我是outer函数')
return inner
outer()
outer()() # 调用内部函数
def tst():
print('我是test函数')
return 'hello'
def demo():
print('我是demo函数')
return tst
def bar():
print('我是bar函数')
return tst()
x = tst()
print(x) # 'hello'
y = demo() # y是test函数
print(y) # <function tst at 0x0000020C2BF47310>
z = y()
print(z) # 'hello'
a = bar() # a是字符串'hello'
print(a) # 'hello'
16. 函数的嵌套
def outer(x):
m = 100
print('我是outer函数')
def inner(): # inner函数是定义在outer函数内部的一个函数
n = 90
print('我是inner函数')
if x > 10:
inner()
return 'hello'
# inner() # 在外部不能调用内部函数
outer(8) # 只调用outer函数
outer(12) # 调用了outer函数和inner函数
17. 闭包
- 如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包
def outer():
x = 10 # x是局部变量
def inner():
y = x + 1
return inner
- 内部函数修改外部函数的局部变量的值
def outer():
x = 10 # x是局部变量
def inner():
# 在内部函数修改外部函数的局部变量的值
nonlocal x # 此时,这里的x 不再是新增的变量,而是外部的局部变量
y = x + 1
x = 20 # 不是修改外部的x 变量,而是在inner函数内部又创建了一个新的变量x
print(y)
return inner
out()() # y的值为11
18. 函数的运用
- 计算一段代码的运行时间
import time
# start = time.time() # time模块里的time方法,可以获取当前时间的时间戳
# # 时间戳是从1970-01-01 00:00:00 UTC 到现在的秒数
# # 从1970-01-01 00:00:00 ~ 2021-04-05 10:15 UTC 东八区 需要减8个小时
# print('start = {}'.format(start))
#
# x = 0
# for i in range(1, 1000000):
# x += i
#
# print(x)
# end = time.time()
# print('end = {}'.format(end))
#
# print('代码的运行耗时 {} 秒'.format(end - start))
def calc_time(fn):
start = time.time()
fn()
end = time.time()
print('代码的运行耗时 {} 秒'.format(end - start))
def demo():
x = 0
for i in range(1, 1000000):
x += i
print(x)
def foo():
print('hello')
time.sleep(1)
print('world')
calc_time(demo)
calc_time(foo)