首页 > 技术文章 > python函数

zhijiyiyu 2022-01-21 08:40 原文

python 函数

一:函数的定义与调用

1.1 什么是函数

函数时组织好的,可重复使用的,用来实现单一或相关联的功能的代码段,它能够提高应用的规模和代码块的重复利用率.


1.2 定义函数

python 中使用def 关键字定义函数,格式如下:

""""
def 函数名(参数列表):
  "函数_文档字符串"
  函数体
	return 表达式
"""
def add(a,b):
  sum = a + b
	return sum

1.3 调用函数

定义函数之后,想要让这些代码能够执行,需要调用函数.

通过 函数名() 即可调用函数

def add(a,b):
    sum = a + b
    return sum

d = add(1,2)
print(d)

调用同文件的函数,只需要在函数下方写函数名,传对应参数即可调用

调用不同文件的函数,需要先导入: from 文件路径 import 函数名(或者*)


二: 函数的参数

2.1 函数的参数传递

如果希望定义的函数可以计算任意两个数的和,我们在定义函数的时候,让函数接收数据.

这就是函数的参数

# 带参函数
def add(a,b): # a,b 被称之为形式参数,形参
    print(a+b)

# 10,30 ; "abc","def" 被称之为实际参数,实参
add(10,30)
add("abc","def")

2.2 默认参数

调用函数时,若默认参数未被传值,则会使用参数的默认值;

若默认参数被传入了值,则会使用传入的新值

定义函数时,可以给函数的参数指定默认值,这个被指定默认值的参数就被称为默认参数

带有默认值的参数一定要位于参数列表的末尾.否则程序会报错

# 演示参数默认值
def add(a, b=3):
    print(a+b)

# 值传递了参数a,没有传递给b,所以b使用默认值
add(a=11)
# 传递了值给b,b使用传递的值
add(a=22,b=33)

# 输出结果
14
55

有默认的参数,可以不赋值,直接使用默认值

如果对有默认值的参数赋值,则该参数的值为新值

无默认值的参数不可以定义在有默认值的参数之后


2.3 不定长参数

若希望函数被调用时能够传入比定义时更多的参数,可以在定义函数时使用不定长参数

加* 的参数,会以元祖的形式存放未命名的参数

加**的参数,会以字典的形式存放未命名的参数。即以key = value的参数


2.3.1 元组形式的不定长参数

"""
def 函数名([formal_args,]*args,**kwargs):
    "函数_文档字符串"
    函数体、
    return 表达式
"""

# 加* 的参数 *args,会以元祖的形式存放未命名的参数
def test1(a, b, *args):
    print(a)
    print(b)
    print(args)

# 没有给不定长参数赋值,会显示空元组
test1(11, 22)

print("------")

#给不定长参数赋值,则会元组形式,存放多个值
test1(11, 22, 33, 44, 55)

# 输出结果:
11
22
()
------
11
22
(33, 44, 55)

2.3.2 字典形式不定长参数

#以 **kwargs格式的不定长参数会以字典形式存放命名的参数
def test1(**kwargs):
    print(kwargs)

#赋值时,需要以key=value 形式赋值
test1(a=1, b=2, c=3)

#输出结果:
{'a': 1, 'b': 2, 'c': 3}

如果是多个可变参,如*a,*b 则报错重复的可变参

如果把可变参放前面,传参的时候必须指定

一般,可变长度的参数写在不可变参数的后面


2.4 集合类型的地址作为值

集合类型的地址,就是变量的值,只要地址不变,地址内元素怎么改变

def add(a):
    for x in range(len(a)):
        a[x] += 10


lst = [10, 20, 30]
add(lst)
print(lst)

# 输出结果:
[20, 30, 40]


三:函数的返回值

3.1 定义函数的返回值

python 中使用return语句返回结果.在函数有了返回值之后,我们可以使用变量接受函数返回值,或者使用print打印

def add(a, b):
    sum = a + b
    return sum

# 先使用变量接受返回值,在打印变量
result = add(10, 20)
print(result)

# 直接打印
print(add(90, 100))

# 输出结果
30
190


3.2 函数的四种类型

根据函数的参数和返回值,函数可以分为四种类型

  • 无参数,无返回值函数
  • 无参数,有返回值函数
  • 有参数,无返回值函数
  • 有参数,有返回值函数

3.2.1 无参数,无返回值函数

def menu():
    print("-------")
    print("小当家大排档菜单")
    print("西红柿炒鸡蛋")
    print("宫保鸡丁")
    print("红烧排骨")
    print("-------")


menu()

# 输出结果:
-------
小当家大排档菜单
西红柿炒鸡蛋
宫保鸡丁
红烧排骨
-------

3.2.2 无参数,有返回值的函数

def temperature():
    return 24


result = temperature()
print("当前温度为:",result)

# 输出结果:
当前温度为: 24


3.2.3 有参数,无返回值的函数

def add(a, b):
    sum = a + b
    print("结果为:", sum)

add(10, 20)

#输出结果:
结果为: 30


3.2.4 有参数,有返回值的函数

def count_add(num):
    sum = 0
    for i in range(num+1):
        sum += i
    return sum  # 使用结果作为返回值

  
  
n = int(input("请输入一个整数:"))

#使用一个变量接收函数返回值
result = count_add(n)
print("从0加到%i的和是" %n, result)

# 输出结果:
请输入一个整数:100
从0加到100的和是 5050

四:函数的嵌套调用

# 演示函数的嵌套调用
def func_one():
    print("----func_one start----")
    print("这里是func_one函数执行代码")
    print("----func_one end----")


def func_two():
    print("----func_two start----")
    func_one()  #在函数func_two中调用函数func_one
    print("----func_two end----")


func_two()

# 输出结果:
----func_two start----
----func_one start----
这里是func_one函数执行代码
----func_one end----
----func_two end----


五: 变量的作用域

5.1: LEGB原则

  • python中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的.
  • 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.
  • python 的作用域一共有四种:
    • L (Local):函数内的区域,包括局部变量和参数
    • E (Enclosiong): 外面嵌套函数区域,常见的是闭包函数的外层函数
    • G (Global): 全局作用域.
    • B (Built-in) :内建作用域
  • python中变量是按照 L ---> E ---> G ---> B 的顺序查找的
  • python在查找变量的时候会优先取函数内作用域中查找,若没有找到便会到嵌套函数作用域中查找,再找不到就去全局作用域中查找,最后再去内建作用域中查找

局部变量

  • 所谓局部变量,就是在函数内部定义的变量
  • 局部变量的作用域是函数内部,说明它旨在定义它的函数中有效,一旦函数结束就会消失

全局变量

  • 定义在函数外的变量拥有全局作用域
  • 全局变量可以在整个程序范围内访问.
  • 如果出现全局变量和局部变量名字相同的情况,则在函数中有限访问局部变量

# 这是全局变量a
a = 10


def test():
    # 这是定义在函数内部的变量a.它只能作用在函数内部
    a = 20
    # 所以,在print 变量a的值时,会先去函数内作用域查找
    print("a的值是:", a)


test()

# 这里不在函数内部,因此函数内的变量a不起作用.回去找全局变量a
print("a的值is:", a)

# 输出结果:
a的值是: 20
a的值is: 10


5.2 global和nonlocal关键字

5.2.1 global关键字

global关键字用来在函数或者其他局部作用域中使用全局变量

a = 100


def test():
    global a
    a += 100
    print(a)

test()

# 输出结果
200


5.2.2 nonlocal关键字

nonlocal 是 python 内置的关键字,其作用是可以在内层函数内声明一个外部函数的变量,它的功能与global 相似,nonlocal 本质上是介于 全局作用域和局部作用域之间的,它仅在函数的嵌套使用时才起作用。

def func_one():
    count = 1

    def func_two():
        nonlocal count
        count = 12

    func_two()
    print(count)


func_one()

# 输出结果:
12

六: 递归函数与匿名函数

6.1 递归 函数

一个函数内部可以调用其他函数.但是如果一个函数子啊内部不是调用其他函数,而是调用自己本身的话,这个函数就是递归函数

# 演示递归函数

b = 0


def a(b):
    b += 1
    if b <= 3:
        print("第%i次调用开始" % b)
        a(b)
    print("第%i次调用结束" % b)


a(b)

# 输出
"""
第1次调用开始
第2次调用开始
第3次调用开始
第4次调用结束
第3次调用结束
第2次调用结束
第1次调用结束

"""

image-20220120111949424

def jiecheng(n):
    # 1 的阶乘结果就是1
    if n == 1:
        # 使用return 返回结果.
        return n
    else:
        # 使用return返回结果,使其可以被调用.
        # 让n -1 ,使得n 的值不断减小
        return n * jiecheng(n - 1)


num = int(input("请输入一个整数:"))

result = jiecheng(num)

print("%s的阶乘是:" % num, result)


#输出结果:
请输入一个整数:5
5的阶乘是: 120
  
#整个代码运行过程是:
"""
jiecheng(5)
==>5 * jiecheng(4)
==>5 * (4 * jiecheng(3))
==>5 * (4 * (3 jiecheng(2)))
==>5 * (4 * (3 * (2 * jiecheng(1))))
==>5 * (4 * (3 * (2 * 1)))
==>5 * (4 * (3 * 2))
==>5 * (4 * 6)
==>5 * 24
==>120 
"""

# 使用递归实现阶乘计算
def jiecheng(num, result):
    # result 获取乘积.开始,result值为"输入的数乘以num 乘以 1"
    result *= num
    
    # 每次被调用,num值-1,当值大于等于时,就继续调用函数.
    # 效果为每次都是上一轮累计的result*num的乘积,在乘以num值
    num -= 1
    if num >= 1:
        jiecheng(num, result)
    # 当值等于0时,就不在调用,而是输出print语句
    if num == 0:
        print(n,"的阶乘是:",result)


n = int(input("请输入一个整数:"))

a = 1
jiecheng(n, a)

# 输出结果:
请输入一个整数:5
5 的阶乘是: 120
  

#计算过程:
"""
jiecheng(5,1)
result = 5 * 1 =5 ;num = 5 -1 =4
===>
jiecheng(4,5)
result = 5 * 4 =20; num = 4 -1 =3
===>
jiecheng(3,20)
result = 20 * 3 =60; num = 3 -1 =2
===>
jiecheng(2,60)
result = 60 * 2 =120; num = 2 -1 =1
===>
jiecheng(1, 120)
result = 120 * 1 =120; num  = 1 -1 =0
===> num =0 
n = 5,result=120
print("5的阶乘是120")
"""

# 使用递归实现阶乘计算
result = 1


def jiecheng(num):
    global result
    result *= num
    num -= 1

    if num >= 1:
        jiecheng(num)


n = int(input("请输入一个整数:"))

jiecheng(n)

print(n, "的阶乘是:", result)


6.2 匿名函数

匿名函数就是没有名称的函数,也就是不再使用def语句定义的函数.

如果要定义匿名函数,则需要使用lambda关键字.

  • lambda [arg1 [,arg2,....argn]]:expression
# 演示匿名函数
result = lambda a, b: a + b
print("运行结果:", result(10, 20))
print("运行结果:", result(20, 20))

# 输出结果:
运行结果: 30
运行结果: 40

匿名函数与普通函数的区别:

  • 普通函数在定义时有名称,而匿名函数没有
  • 普通函数的函数体中包含有多条语句,而匿名函数的函数体只能是一个表达式
  • 普通函数可以实现比较复杂的功能,而匿名函数课实现的功能比较简单

七 时间和日期函数


7.1 时间函数

在python 中,通常由如下几种方式表示时间

  • 时间戳
  • 格式化的时间字符串
  • 时间元组(struct_time

7.1.1 时间戳

时间戳表示从1970年1月1日00:00:00 开始按秒计算的偏移量

import time  #引入时间模块

ticks = time.time()
print("当前时间戳为:",ticks)

# 
当前时间戳为: 1642693762.2411685

7.1.2 格式化时间字符串

我们可以使用time模块的strftime 方法来格式化日期.

import time

print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
格式化符号 含义
%y 两位数的年份表示(00~99)
%Y 四位数的年份表示(000~9999)
%m 月份(01~12)
%d 月内中的一天
%H 24小时制小时数(0~23)
%l 12小时制小时数(01~12)
%M 分钟数(00~59)
%S 秒(00~59)

7.1.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
6 tm_wday 0到6
7 tm_yday 1到366
8 tm_isdst -1,0,1,-1是决定是否为夏令时的旗帜
  • time.altzone
    • 返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用。
  • time.asctime([tupletime])
    • 接受时间元组并返回一个形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07分14秒)的24个字符的字符串。
  • time.clock( )3.8版本淘汰 time.process_time()
    • 用以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用
  • time.ctime([secs])
    • 作用相当于asctime(localtime(secs)),未传入secs参数相当于asctime()。
  • time.gmtime([secs])
    • 接收时间辍(1970年1月1日00:00:00后经过的浮点秒数)并返回格林威治天文时间下的时间元组
  • time.localtime([secs])
    • 接收时间辍( 1970年1月1日00:00:00后经过的浮点秒数)并返回当地时间下的时间元组。
  • time.mktime(tupletime)
    • 接受时间元组并返回时间辍。
  • time.sleep(secs)
    • 推迟调用线程的运行,secs指秒数。
  • time.strftime(fmt[,tupletime])
    • 接收时间元组并返回以可读字符串表示的当地时间,格式由fmt决定。
  • time.strptime(str,fmt='%a %b %d %H:%M:%S %Y')
    • 根据fmt的格式把一个时间字符串解析为时间元组。
  • time.time( )
    • 返回当前时间的时间戳。
  • time.tzset()
    • 根据环境变量TZ重新初始化时间相关设置。
  • time.timezone
    • 表示当地时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲;<=0大部分欧洲,亚洲,非洲)
  • time.tzname
    • 包含一对根据情况不同而不同的字符串,分别是带夏令时的本地时区名称,和不带名称的。

7.2 日历函数


  • calendar.calendar(year,w=2,l=1,c=6)
    • 返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。每日宽度间隔为w个字符。每行长度为21* W+18+2* C。l是每星期行数。
  • calendar. firstweekday()
    • 返回当前每周起始日期的设置。默认情况下,首次载入calendar模块时返回0,即星期一。
  • calendar.isleap(year)
    • 如果是闰年返回True,否则为False。
  • calendar.leapdays(y1,y2)
    • 返回Y1、Y2两年之间的闰年总数。
  • calendar.month(year,month,w=2,l=1)
    • 返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数
  • calendar.monthcalendar(year,month)
    • 返回一个整数嵌套列表。每个子列表装载代表一个星期的整数。year年month月外的日期都设为0;范围内的日期都使用该月第几日表示,从1开始。
  • calendar.monthrange(year,month)
    • 返回两个整数,第一个整数是该月星期几的日期码,第二个整数是该月的日期码。日从0(星期一)到6(星期日);月从1到12。
  • calendar.prcal(year,w=2,l=1,c=6)
    • 相当于print(calendar.calendar(year,w,l,c))
  • calendar.setfirstweekday(weekday)
    • 设置每周的起始日期码。日期码的范围为0(星期一)~6(星期日)
  • calendar.prmonth(year,month,w=2,l=1)
    • 相当于print(calendar.calendar(year,w,l,c))
  • calendar.timegm(tupletime)
    • 接受一个时间元组,返回该时刻的时间辍(1970纪元后经过的浮点秒数)
  • calendar.weekday(year,month,day)
    • 返回给定日期的日期码。星期为0(星期一)~6(星期日);月份为 1(1月)~ 12(12月)。

八 随机函数


8.1 random.random()

用于生成一个0到1的随机符点数N:0 <= N < 1.0。

import random # 导入模块

print("random():",random.random())

#输出结果:
random(): 0.93203272738572


8.2 random.uniform(a,b)

返回a、b之间的随机浮点数,范围为[a,b] 。

import random # 导入模块

print("random:",random.uniform(50,100))

#输出结果:
random: 57.08371353402669


8.3 random.randint(a,b)

返回a、b之间的随机整数N,N的取值范围为a<=N<=b,且a一定要小于b。

import random # 导入模块


for i in range(5):
    print(random.randint(10,20))
    
# 输出结果:
20
19
15
20
12

8.4 random.randrang([start], stop[, step])

返回指定递增基数集合中的一个随机数,基数默认值为1。其中,start参数用于指定范围的开始值,其包含在范围内;end参数用于指定范围的结束值,其不包含在范围内;step表示递增基数。

import random # 导入模块

for i in range(5):
    print(random.randrange(10, 20, 2))

#输出结果:
12
10
18
18
16

8.5 random.choice(sequence)

​ 从sequence中返回一个随机元素。 sequence可以是列表、元组、字符串。

import random # 导入模块

a = [1, 2, 3, 4, 5, 6]

for i in range(3):
    print(random.choice(a))

# 输出结果:
3
2
6

8.6 random.shuffle(x[,random])

​ 将列表中的元素打乱顺序,俗称为洗牌。

import random # 导入模块

a = [1, 2, 3, 4, 5, 6]

random.shuffle(a)
print(a)

#输出结果:
[5, 1, 6, 3, 2, 4]


8.7 random.sample(sequence,k)

从指定序列中随机获取k个元素作为一个片段返回,sample函数不会修改原有序列 。

import random # 导入模块

a = [1, 2, 3, 4, 5, 6]

result = random.sample(a, 2)

print(result)
print(a)

# 输出结果:
[4, 3]
[1, 2, 3, 4, 5, 6]

推荐阅读