函数基础
函数简介
- 定义:具有特定功能的一段代码。
- 优点:1、 可以减少代码的重复书写 2、可以将功能的实现着和使用者分开,提高开发效率
- 分类:
分类 | 定义 |
---|---|
库函数 | print、input、type等 |
自定义 | 用户自己封装的函数 |
函数使用
- 基本格式:
def 函数名([参数列表]):
函数体
- 函数名:
- 像变量名一样,只要符合标识符命名规范即可。
- 函数调用:
- 调用格式:函数名([参数])
- 说明:函数不调用是不执行的,只有调用后才会执行
- 函数分类
-
说明:按照有无参数及返回值来分
-
示例:
-
# 无参无返回值
def print_ten_hello():
for i in range(10):
print('hello world!')
# 无参:调用时无需传参数
# 无返回值:执行完函数的返回值为None
# None的一个作用是为了不报错,仅仅只是这样
# ret=print_nine_hello()
# print(print_nine_hello())
# 带参无返回值
def print_n_hello(n):
for i in range(n):
print('hello world!')
# 需要传递参数
print_n_hello(6)
# 带参有返回值
def add(a, b):
ret = a+b
# 使用关键字return返回内容
# 一旦执行return,函数立即结束
# return后面会返回函数返回值
return ret
print(add(4,5))
函数参数
-
形参:形式参数,就是写在函数定义处的参数。
-
实参:实际参数,就是在函数调用时传递的参数。
-
位置参数:函数定义时没有默认值的参数,也叫必传参数。调用时实参与定义时的形参要一一对应
-
默认参数:函数定义时有默认值的参数,调用函数时可以不传递该参数。默认参数需要放在末尾
-
关键字参数:函数调用时指定参数的名字,参数的位置就无需考虑。
-
可变长度参数:
def var_len_args(a, b, *args, name='张三', **kwargs):
print(a, b)
# 是一个元组,用于保存多传的位置参数
print(args)
# 是一个字典,用于保存多传的关键字参数
*的使用
def show(a, b=8):
print(a, b)
lt = [2, 3]
# show(lt[0], lt[1])
# 与上式等价,*是将列表展开,然后作为位置参数传递给函数
show(*lt)
d = {'a': '李四', 'b': 18}
# show(a=d['a'], b=d['b'])
# 与上式等价,**式将字典展开,然后作为关键字参数传递给函数
show(**d)
函数进阶
- 函数定义的位置并不是随意的,函数调用一定要放在定义之后,也就是先定义再调用。
- 函数的名字不可以相同,虽然语法不报错,但是后者会覆盖前面的同名函数。
- 函数内部可以定义另一个函数,函数内部定义的函数叫内部函数,它是很多高级功能实现的基础。
常用函数
- 内置函数(无需导入)
函数名 | 含义 |
---|---|
打印,输出 | |
input | 输入 |
type | 获取类型 |
len | 统计元素个数 |
range | 产生连续的整数对象 |
enumerate | 枚举可迭代对象 |
ord | 字符转ASCII |
chr | ASCII转字符 |
abs | 求绝对值 |
max | 最大值 |
min | 最小值 |
sum | 求和 |
pow | 求幂 |
round | 四舍五入 |
hex | 十六进制 |
oct | 八进制 |
bin | 二进制 |
类型转换 | int、float、str、bool、set、list、tuple、dict |
模块函数(需要导入)
函数名 |
---|
time |
math |
sys |
import time
#
# while True:
# print('Hello world!')
# time.sleep(1)
import math
print(math.e)
print(math.pi)
print(math.ceil(3.1))
print(math.floor(3.9))
print(math.sqrt(4))
# 度转换为弧度
print(math.radians(360))
# 弧度转换为度
print(math.degrees(math.pi))
import sys
# 是一个列表,保存所有的命令行参数
print(sys.argv)
函数使用
变量作用域
- 块级作用域
if True:
name = 'xiaoming'
# 没有块级作用域
print(name)
- 局部作用域
def test():
a = 10
test()
# 局部变量:在函数内部定义的变量,只能在函数内部使用
# print(a)
- 全局作用域
# 全局变量:定义在函数外部的变量,拥有全局的作用
num = 10
def show():
# 函数内部可以使用外部定义的变量
# print(num)
# 若想更改外部变量,需要进行global声明
global num
# 不能更改外部的全局变量,而是定义了一个局部变量
num = 20
show()
print(num)
- nonlocal使用
def wai():
n = 100
def nei():
# 使用外部函数的局部变量,需要进行声明才可更改
nonlocal n
# 内部函数可以使用外部函数的局部变量,但是不能更改
n = 200
print(n)
nei()
print(n)
wai()
匿名函数
- 函数可以像普通变量一样进行赋值
def test():
print('for test')
print(test.__name__)
# 函数可以像普通变量一样进行赋值
a = test
print(a.__name__)
a()
- 函数可以作为一个函数的参数
def show(func):
func()
# 函数作为参数传递
show(test)
-
匿名函数
- 说明:当将函数作为参数传递时,若函数只需要一次,没有必要单独定义函数,可以使用匿名函数解决。
- 格式:lambda 参数列表: 表达式
参数列表与定义函数是一样,可以是多个,多个参数之间使用逗号分隔
表达式就是返回值,不需要使用return关键字 - 示例:
lt = [
{'name': 'dahua', 'age': 18, 'height': 165},
{'name': 'erhua', 'age': 16, 'height': 160},
{'name': 'dagou', 'age': 20, 'height': 175},
{'name': 'ergou', 'age': 15, 'height': 155}
]
def key(d):
return d['height']
# lt.sort(key=key)
lt.sort(key=lambda d: d['age'])
for i in lt:
print(i)
闭包使用
- 定义:具有执行环境的函数
外部函数中定义一个内部函数
内部函数中使用外部函数的局部变量
外部函数将内部函数作为返回值返回
此时的内部函数就叫闭包
- 示例:
def wai(n):
# 定义内部函数
def nei():
# 内部函数中使用外部函数的局部变量
return n * n
# 内部函数作为返回值
return nei
f1 = wai(10)
f2 = wai(4)
print(f1())
print(f2())
装饰器
-
作用:当需要改变一个函数原有的功能时,但是不想/不能改变原来的函数,可以通过装饰器解决
-
使用:
- 装饰器其实就是一个函数,该函数有一个参数(函数类型),返回一个闭包
- 在返回的闭包中调用传递进来的函数,然后在调用函数的前后就可以添加内容
-
示例:
def zhuangshiqi(func):
def wrapper():
print('开始装饰')
func()
print('装饰结束')
return wrapper
@zhuangshiqi
# 相当于执行了:test = zhuangshiqi(test)
def test():
print('for test')
# t2 = zhuangshiqi(test)
# t2()
# test = zhuangshiqi(test)
test()
@zhuangshiqi
def demo():
print('原有内容')
demo()
-
分类:
- 装饰无参无返回值的函数
def shuai(func):
def wrapper():
print('拉风的暴龙眼镜')
func()
print('鳄鱼牌大头皮鞋')
return wrapper
@shuai
def diaosi():
print('杰哥,屌丝一枚')
diaosi()
- 装饰带参无返回值的函数
def zhuangshiqi(func):
def wrapper(*args, **kwargs):
print('开始装饰')
func(*args, **kwargs)
print('装饰结束')
return wrapper
@zhuangshiqi
def test(n):
print('I like num {}'.format(n))
test(250)
装饰带参有返回值的函数
def zhuangshiqi(func):
def wrapper(*args, **kwargs):
print('开始装饰')
ret = func(*args, **kwargs)
print(ret)
print('装饰结束')
return ret
return wrapper
@zhuangshiqi
def add(a, b):
return a + b
print(add(3, 5))
递归函数
定义:在函数内部调用自己的函数就叫递归函数。
组成:
函数内部调用自己
终止条件(停止调用自己的条件)
核心算法
特点:
代码简单
可读性差
瞬间占用内存比较大,终止条件出错立即崩溃
能不使用就不使用,就是在不得不用的时候再使用(遍历目录)
函数零碎知识
- 灵活的if-else
a = 3 if False else 5
# 上下两种写法等价
# if False:
# a = 3
# else:
# a = 5
print(a)
- 灵活的and/or
# 前面的表达式为真,才会执行后面的表达式
a = True and 3
print(a)
# 前面的表达式为假,后面的表达式根本无需执行
b = False and 5
print(b)
# 前面的表达式值真,后面的表达式无需执行
c = True or 3
print(c)
# 前面的表达式为假,需要后面表达式的判断
d = False or 5
print(d)
- 类型判断
a = 250
# print(type(a))
# if type(a) == int:
if type(a) == type(1):
print('a', '是一个整数')
# 判断一个对象是不是某种类型的一个实例
print(isinstance(a, int))
print(isinstance(a, str))
def test():
pass
# print(type(test))
# 用能使用这种方式进行函数类型的判断
# print(isinstance(test, function))
from inspect import isfunction
# 判断一个标识符是否是函数
print(isfunction(test))
print(isfunction(a))
- 变量地址
# 获取变量地址
print(id(a))
b = 10
print(id(b))
# a和b地址相同
lt = [1, 2, 3]
print(id(lt))
lt2 = [1, 2, 3]
print(id(lt2))
# lt和lt2地址不同
生成器
- 使用场景:
在使用列表时,很多时候我们不会一下子使用数据,通常都是一个一个使用;当数据量较大的时候,定义一个列表会是程序内存占用突然增大,为了解决此类问题,python中引入了生成器。
- 生成方式:
- 方式1:将列表生成式的[]改为()即可
# 列表生成式
# lt = [i for i in range(10)]
# print(lt)
lt = (i for i in range(3))
print(lt)
# 可以转换为列表
# print(list(lt))
# 可以进行遍历
# for i in lt:
# print(i)
# 可以一个一个提取,当提取结束后再次提取会报StopIteration错
print(next(lt))
print(next(lt))
print(next(lt))
print(next(lt))
- 方式2:在函数中使用yield关键字
# 当数据量特别大的时候,占用内存会突然增大
def test(n):
lt = []
for i in range(1, n+1):
lt.append(i)
return lt
print(test(10))
'''
def test(n):
for i in range(1, n+1):
# 执行到此处,函数会返回yield后的内容,然后会停止在这里
yield i
t = test(3)
# print(t)
# 可以一个一个提取
# print(next(t))
# print(next(t))
# print(next(t))
# 可以遍历
# for i in t:
# print(i)
# 可以转换为列表
print(list(t))
- 使用说明:
生成器对象保存的是特定数据的生成算法,而不是特定的所有数据
使用任意一种方式操作,都是单次的
生成器可以做的操作:遍历、next、转换为列表
迭代器
-
定义:能够使用for-in进行遍历,并且可以使用next函数进行迭代的对象
-
说明:
生成器就是一种特殊的迭代器
判断一个对象是否是迭代器
from collections import Iterator
# 判断是否是迭代器
print(isinstance(lt, Iterator))
字符串及容器类型的对象都不是迭代器,他们都是可迭代对象
可迭代对象
-
定义:可以使用for-in遍历的对象,都是可迭代对象
-
说明:
- 字符串及容器类型的对象都是可迭代对象
- 迭代器一定是可迭代对象
- 判断一个对象是否是可迭代对象
from collections import Iterable, Iterator
lt = [1, 2, 3]
# 判断是否是可迭代对象
print(isinstance(lt, Iterable))
# 判断是否是迭代器
print(isinstance(lt, Iterator))
- **iter:**可以将可迭代对象转换为迭代器
lt = [1, 2, 3]
# 将可迭代对象转换为迭代器
lt2 = iter(lt)
random
- random
import random
# 生成指定范围内的随机整数
print(random.randint(1, 10))
# 生成0~1之间的随机小数
print(random.random())
# 生成指定范围内的随机整数,可以指定步幅
print(random.randrange(1, 10, 2))
lt = [1, 2, 3, 4, 5, 6, 7]
# 从容器对象或字符串中随机挑选一个元素
print(random.choice(lt))
# print(random.choice('ashdaiapo'))
# 从容器对象中随机挑取指定个数的元素
print(random.sample(lt, 3))
# 从容器对象中随机挑取一个元素,sample函数个数为1的情况
print(random.choices(lt))
# 打乱一个列表
random.shuffle(lt)
print(lt)
高级函数
-
map
-
参数:
func:一个函数
iter:一个可迭代对象 -
功能:
将可迭代对象遍历,每个元素都使用该函数处理一遍,然后返回,保存这种算法的迭代器 -
使用:
-
from collections import Iterator
lt = [1, 2, 3, 4, 5]
def pingfang(n):
return n * n
# 返回map对象,是一个迭代器
# ret = map(pingfang, lt)
ret = map(lambda x: x*x, lt)
print(isinstance(ret, Iterator))
print(list(ret))
# print(next(ret))
# print(next(ret))
-
filter
- 参数
function:一个函数
iterable:可迭代对象 - 功能:
- 参数
使用function依次作用于可迭代对象中的每个元素,当返回结果为True时保留该元素。返回filter对象,是一个迭代器。
- 示例:
lt = [1, 2, 3, 4, 5]
def oushu(n):
return n%2 == 0
# 返回filter对象,是一个迭代器
# ret = filter(oushu, lt)
ret = filter(lambda x: x%2 != 0, lt)
print(ret)
print(list(ret))
# print(next(ret))
-
reduce
- 参数
function:一个函数
sequence:一个序列 - 功能:
首先从序列中取出前两个元素,作为function的参数处理一下
处理完的结果与下一个元素再使用function处理一下
处理结束,将处理完的结果返回 - 示例:
- 参数
from functools import reduce
lt = [1, 2, 3, 4, 5]
def add(a, b):
return a + b
# ret = reduce(add, lt)
# ret = reduce(lambda x, y: x*y, lt)
ret = reduce(lambda x, y: x*10 + y, lt)
print(ret)