文章目录
1. 什么是函数
- 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
- 函数能提高应用的模块性,和代码的重复利用率。你已经知道 Python 提供了许多内建函数,比如 print()。但你也可以自己创建函数,这被叫做用户自定义函数。
2. 函数的定义
Python 使用 def 关键字定义函数,语法格式如下:
def functionname( parameters ):
"函数_文档字符串"
function_suite
return [expression]
定义函数的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
- 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的 return 相当于返回 None。
不带返回值的函数
def function():
print("*")
print("* *")
print("* * *")
print("* * * *")
function() #调用函数
# 结果
*
* *
* * *
* * * *
带返回值的函数
def function():
print("***")
return 1
function()
# 结果
***
//有返回值,如果只是单纯的调用,返回的还是函数的过程,return 的值没有意义。
------------------------------------
def function():
print("***")
return 1
# function()
print(function())
# 结果
***
1
3. 函数的调用
函数的调用有两种情况:
- 在函数当前文件调用
- 在其他文件调用函数
当前文件调用:
//当前文件调用,在函数下面输入函数名,传对应参数即可
def function(a,b):
print(a+b)
function(1,2)
# 结果
3
不同文件调用:
//不同文件调用需要先导入 {from filedir import funcname/* ("*"代表该文件的所有函数)}
# 例如:我在 2.py 想要调用 test 包里面的 1.py 的函数
--- 1.py 函数为:
def function(a,b): #像 a,b 这类不确定的参数一般叫做形参
print(a+b)
function(1,2) # 1,2 这种具体的参数叫做实参
--- 2.py 调用 1 中的 function 函数
from test.1 import function
function
# 结果
3
4. 函数的参数
4.1 参数的传递
- 在 python 中,类型属于对象,变量是没有类型的。
- 在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list, dict 等则是可以修改的对象。
- python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
# 这种就是参数的传递
def function(a,b):
print(a+b)
function(1,2)
python 函数的参数传递两种类型:
-
不可变类型:类似 c++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。比如在 fun(a) 内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
-
可变类型:类似 c++ 的引用传递,如列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响。
4.2 默认参数
- 定义函数时,可以给函数的参数指定默认值,这个被指定默认值的参数被称为默认参数。
- 带有默认值的参数一定要位于参数列表的末尾。否则程序会报错。
def func(name,age=35):
print("name:",name)
print("age:",age)
func(name="miki")
func(age=9,name="miki")
# 结果
name: miki
age: 35
name: miki
age: 9
# 第一个 func() 中给 name 进行了赋值,age 是 func 函数自己定义的
# 第二个 func() 中给两个变量都进行了赋值
4.3 不定长参数
- 若希望函数被调用时能够传入比定义时更多的参数,可以在定义函数时使用不定长参数。
语法:
def 函数名([formal_args,] *args, **kwargs):
"函数_文档字符串"
函数体、
return 表达式
> 加星号 * 的参数 args 会以元组的形式存放未命名的参数。
> 加 ** 的参数 kwargs 会以字典的形式存放命名的参数,即形如 key=value 的参数。
示例:
def test(a,b,*args):
print(a)
print(b)
print(args)
test(11,22)
# 结果
11
22
() # *.args 以元组形式存放参数,该函数元组无元素
--------------------------------------
def test(a,b,*args):
print(a)
print(b)
print(args)
test(11,22,33,44,55)
# 结果
11
22
(33, 44, 55) # 该函数元组传入了三个元素
--------------------------------------
def test(a,b,*args,**kwargs):
print(a)
print(b)
print(args)
print(kwargs)
test(11,22,33,44,55,66,77,88,99)
# 结果
11
22
(33, 44, 55, 66, 77, 88, 99)
{} # **kwargs 存放键值对形式的元素,该函数字典为空
--------------------------------------
def test(a,b,*args,**kwargs):
print(a)
print(b)
print(args)
print(kwargs)
test(11, 22, 33, 44, 55, 66, 77, m=88, n=99)
# 结果
11
22
(33, 44, 55, 66, 77)
{'m': 88, 'n': 99} # test() 语句中可以看出有两个键值对
5. 函数的返回值
return [表达式]
语句退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。- 程序运行到所遇到的第一个 return 即返回(退出 def 块),不会再运行第二个 return。(不包括判断语句)
- 要返回两个数值,写成一行即可。
def a(x,y):
if x == y:
return (x,y)
print(a(3,3)) # 结果:(3,3)
----------------------------
def test_return(x):
if x > 0:
return x
else:
return 0
print(test_return(5)) # 结果:5
----------------------------
def gcd(a,b):
if a%b == 0:
return b
else:
gcd(b,a%b)
print(gcd(4,2)) # 结果:2
6. 函数的四种类型
根据函数的参数和返回值,函数可以分为四种类型:
- 无参数,无返回值的函数
def print_menu():
print('-----点菜系统-----')
print('1.羊肉涮锅')
print('2.牛肉涮锅')
print('3.猪肉涮锅')
print_menu()
- 无参数,有返回值的函数
def get_tem():
return 24
tem = get_tem()
print("当前温度为:",tem)
- 有参数,无返回值的函数
def test(x,y):
c = x + y
print(c)
test(2,1)
- 有参数,有返回值的函数
def test(x,y):
c = x + y
return(c)
b = test(3,4)
print(b)
7. 函数的嵌套调用
- 函数有可见范围,这就是作用域的概念。内部函数不能被外部直接使用,会抛 NameError 异常。
- 全局作用域(global):在整个程序运行环境中都可见。
- 局部作用域:在函数、类等内部可见;局部变量使用范围不能超过其所在的局部作用域。
- 函数有此概念,变量也有。
def outer():
for i in range(3):
i += 1
def inner():
for j in range(3):
j += 1
print("这是内函数")
inner()
print("这是外函数")
inner() # 该语句无法执行,内部循环无法被外部循环调用
outer()
-----------------------------
def f1(): # 1
def f2(): # 3
print('from f2') # 5
def f3(): # 6
print('from f3') #8
f3() # 7
f2() # 4
f1() # 2
# 结果
from f2
from f3
8. 变量的作用域
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的,看如下示例:
a = 10
def test():
a = 20
print('a 的值为 %d'%a)
test() # 结果:20
//我们调用的 test() 函数执行的内部运算,外部 a 的值影响不到内部
LEGB 原则:变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有 4 种。
- L(Local):函数内的区域,包括局部变量和参数。
- E(Enclosing):外面嵌套函数区域,常见的是闭包函数的外层函数。
- G(Global):全局作用域。
- B(Built-in):内建作用域。
Python 中变量是按照 L -》E -》G -》B 的顺序查找的。
Python 在查找变量的时候会优先去函数内作用域中查找,若没有找到便会到嵌套函数作用域中查找,再找不到就去全局作用域中查找,最后再去内建作用域中查找。
局部变量:
- 所谓局部变量,就是在函数内部定义的变量。
- 局部变量的作用域是函数内部,说明它只在定义它的函数中有效,一旦函数结束就会消失。
全局变量:
- 定义在函数外的变量拥有全局作用域。
- 全局变量可以在整个程序范围内访问。
- 如果出现全局变量和局部变量名字相同的情况,则在函数中优先访问局部变量。
global 关键字
- global 关键字用来在函数或其他局部作用域中使用全局变量。
a = 100
def test():
global a
a += 100
print(a)
test() # 结果:200
// 我们通过 global 关键字在 test() 函数内部引用了外部变量 a 的值。
nonlocal 关键字
- 使用 nonlocal 关键字可以在一个嵌套的函数中修改嵌套作用域中的变量(非全局变量)。
- https://www.cnblogs.com/tallme/p/11300822.html
# nonlocal 关键字用来在函数或其他作用域中使用外层(非全局)变量。
def func():
count = 1
def func_in():
nonlocal count
count = count + 1
func_in()
print(count)
func() # 结果:2
---------------------------
def work():
x = 0
def new_work():
nonlocal x
x = x + 3
return x
return new_work()
print(work()) # 结果:3
---------------------------
def dosometing():
a =25
def add(x):
nonlocal a
a=a+x
return a
return add
f=dosometing()
print(f(5)) # 结果:30
print(f(5)) # 结果:35
print(f(5)) # 结果:40
9. 递归函数
- 一个函数的内部可以调用其他函数。但是,如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数。
- https://www.cnblogs.com/haitaoli/p/9692649.html
计算 1 到 100 之间相加之和:
# 循环
def sum_cycle(n):
sum = 0
for i in range(1,n+1) :
sum += i
print(sum)
sum_cycle(100)
# 递归
def sum_recu(n):
if n > 0:
return n + sum_recu(n - 1)
else:
return 0
sum_recu(100)
sum = sum_recu(100)
print(sum)
计算阶乘:
def fact(n):
if n == 1:
return 1
return n * fact(n - 1)
print(fact(5)) # 输出结果: 120
print(fact(1)) # 输出结果: 1
print(fact(3)) # 输出结果:6
10. 匿名函数
- 匿名函数就是没有名称的函数,也就是不再使用 def 语句定义的函数。如果要定义匿名函数,则需要使用 lambda 关键字。
- https://blog.csdn.net/weixin_43790276/article/details/90730797
与普通函数相比,匿名函数有很多不同的地方:
- 普通函数在定义时有名称,而匿名函数没有名称。
- 普通函数的函数体中包含有多条语句,而匿名函数的函数体只能是一个表达式。
- 普通函数可以实现比较复杂的功能,而匿名函数可实现的功能比较简单。
格式:
lambda [arg1 [,arg2......argn]]:expression
//[arg1 [,arg2,...argn]] 表示函数的参数,"expression" 表示表达式
示例:
sum = lambda a, b:a + b
print("运行结果:",sum(10,20)) # 30
print("运行结果:",sum(20,20)) # 40
11. 时间函数
在 Python 中,通常有如下几种方式表示时间:
- 时间戳
- 格式化的时间字符串
- 时间元组(struct_time)
https://www.runoob.com/python/python-date-time.html
11.1 时间戳
时间戳表示从 1970 年 1 月 1 日 00:00:00 开始按秒计算的偏移量。
import time; # 引入 time 模块
ticks = time.time()
print("当前时间戳为:", ticks)
# 结果
当前时间戳为: 1642646483.0328028
11.2 格式化的时间字符串
我们可以使用 time 模块的 strftime 方法来格式化日期。
import time
# 格式化成 2022-01-20 10:43:00 形式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
# 结果
2022-01-20 10:43:00
常用格式化符号:(具体见上面链接)
11.3 时间元组
返回时间元组的函数主要有 gmtime()、localtime() 和 strptime()。时间元组共有 9 个字段:
序号 | 属性 | 值 |
---|---|---|
0 | tm_year | 2008 |
1 | tm_mon | 1 到 12 |
2 | tm_mday | 1 到 31 |
3 | tm_hour | 0 到 23 |
4 | tm_min | 0 到 59 |
5 | tm_sec | 0 到 61 (60或61 是闰秒) |
6 | tm_wday | 0到6 (0是周一) |
7 | tm_yday | 1 到 366(儒略历) |
8 | tm_isdst | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
Time 模块包含了以下内置函数,既有时间处理的,也有转换时间格式的:
序号 | 函数及描述 |
---|---|
1 | time.altzone 返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用。 |
2 | [time.asctime(tupletime]) 接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07分14秒)的24个字符的字符串。 |
3 | time.clock( ) 用以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用。 |
4 | [time.ctime(secs]) 作用相当于asctime(localtime(secs)),未给参数相当于asctime() |
5 | [time.gmtime(secs]) 接收时间戳(1970纪元后经过的浮点秒数)并返回格林威治天文时间下的时间元组t。注:t.tm_isdst始终为0 |
6 | [time.localtime(secs]) 接收时间戳(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)。 |
7 | time.mktime(tupletime) 接受时间元组并返回时间戳(1970纪元后经过的浮点秒数)。 |
8 | time.sleep(secs) 推迟调用线程的运行,secs指秒数。 |
9 | [time.strftime(fmt,tupletime]) 接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定。 |
10 | time.strptime(str,fmt=’%a %b %d %H:%M:%S %Y’) 根据fmt的格式把一个时间字符串解析为时间元组。 |
11 | time.time( ) 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。 |
12 | time.tzset() 根据环境变量TZ重新初始化时间相关设置。 |
Time 模块包含了以下 2 个非常重要的属性:
序号 | 属性及描述 |
---|---|
1 | time.timezone 属性 time.timezone 是当地时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲<=0大部分欧洲,亚洲,非洲)。 |
2 | time.tzname 属性time.tzname包含一对根据情况的不同而不同的字符串,分别是带夏令时的本地时区名称,和不带的。 |
11.4 日历函数
此模块的函数都是日历相关的,例如打印某月的字符月历。星期一是默认的每周第一天,星期天是默认的最后一天。更改设置需调用 calendar.setfirstweekday() 函数。模块包含了以下内置函数:
序号 | 函数及描述 |
---|---|
1 | calendar.calendar(year,w=2,l=1,c=6) 返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为21* W+18+2* C。l是每星期行数。 |
2 | calendar.firstweekday( ) 返回当前每周起始日期的设置。默认情况下,首次载入 calendar 模块时返回 0,即星期一。 |
3 | calendar.isleap(year) 是闰年返回 True,否则为 False。>>> import calendar >>> print(calendar.isleap(2000)) True >>> print(calendar.isleap(1900)) False |
4 | calendar.leapdays(y1,y2) 返回在Y1,Y2两年之间的闰年总数。 |
5 | calendar.month(year,month,w=2,l=1) 返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。 |
6 | calendar.monthcalendar(year,month) 返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。 |
7 | calendar.monthrange(year,month) 返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码。日从0(星期一)到6(星期日);月从1到12。 |
8 | calendar.prcal(year,w=2,l=1,c=6) 相当于 print calendar.calendar(year,w=2,l=1,c=6)。 |
9 | calendar.prmonth(year,month,w=2,l=1) 相当于 print calendar.month(year,month,w=2,l=1) 。 |
10 | calendar.setfirstweekday(weekday) 设置每周的起始日期码。0(星期一)到6(星期日)。 |
11 | calendar.timegm(tupletime) 和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间戳(1970纪元后经过的浮点秒数)。 |
12 | calendar.weekday(year,month,day) 返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。 |
在 Python 中,其他处理日期和时间的模块还有:
- datetime 模块
- pytz 模块
- dateutil 模块
12. 随机数函数
random.random()
- 返回 0 与 1 之间的随机浮点数 N,范围为 0<=N<1.0。
import random
# 生成一个随机数
print("random():", random.random())
# 生成第二个随机数
print("random():", random.random())
random.uniform(a,b)
- 返回 a 与 b 之间的随机浮点数 N,范围为 [a,b]。如果 a 的值小于 b 的值,则生成的随机浮点数 N 的取值范围为 a<=N<=b;如果 a 的值大于 b 的值,则生成的随机浮点数 N 的取值范围为 b<=N<=a。
import random
print("random:", random.uniform(50, 100))
print("random:", random.uniform(100, 50))
random.randint(a,b)
- 返回一个随机的整数 N,N 的取值范围为 a<=N<=b。需要注意的是,a 和 b 的取值必须为整数,并且 a 的值一定要小于 b 的值。
import random
# 生成一个随机数N,N的取值范围为12<=N<=20
print(random.randint(12, 20))
# 生成的随机数为N,N 的结果永远为20
print(random.randint(20, 20))
# print(random.randint(20, 10))
# 该语句是错误语句,下限a必须小于上线b
random.randrange([start], stop[, step])
- 返回指定递增基数集合中的一个随机数,基数默认值为 1。其中,start 参数用于指定范围内的开始值,其包含在范围内;end 参数用于指定范围内的结束值。其不包含在范围内;sep 表示递增基数上述这些参数必须为整数。
import random
print(random.randrange(10, 100, 2))
random.choice(sequence)
- 从 sequence 中返回一个随机数,其中 sequence 参数可以是列表、元组或字符串。若 sequence 为空,则会引发 IndexError 异常。
import random
mylist = ["apple", "banana", "cherry"]
print(random.choice(mylist))
random.shuffle(X[,random])
- 用于将列表中的元素打乱顺序,俗称 “洗牌”。
import random
demo_list = ["python", "is", "powerful", "simpel", "and so on..."]
random.shuffle(demo_list)
print(demo_list)
random.sample(sequence, K)
- 从指定序列中随机获取 K 个元素作为一个片段返回,sample 函数不会修改原有序列。
import random
list_num =[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 定义slice为随机在list_num中获取的3个元素
slice = random.sample(list_num, 3)
print(slice)
# 原有的序列没有发生改变
print(list_num)