python函数

python函数

一、函数定义和调用

  • 什么是函数?
  • 如果在开发程序时,需要某块代码多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数
  • 定义函数的格式如下:
def 函数名():
    代码部分

uTools_1651896715754.png

# 定义一个函数,能够完成打印信息的功能
def fun1():
    print("--------------------------")
    print("   ----i love china----   ")
    print("--------------------------")
  • 调用函数

    定义了函数之后,就相当于有了一个具有某些功能的代码,想要让这些代码能够执行,需要调用它

    调用函数很简单的,通过 函数名() 即可完成调用

# 定义完函数后,函数是不会自动执行的,需要调用它才可以
fun1()

#--------------------------
#   ----i love china----   
#--------------------------
  • 练习

    # 定义一个函数
    def fun2(a,b):
        #"2个数求和"
        print(f"{a}+{b}={a+b}")
    
    fun2(11,12)
    
    11+12=23
    

二、函数参数

什么是函数参数

  • 函数取得的参数是你提供给函数的值。
  • 这些参数就像变量一样,只不过它们的值是在我们调用函数的时候定义的

参数的形式

  • 参数在函数定义的圆括号对内指定,用逗号分割。
  • 形参:函数中的参数名称为形参
  • 实参:提供给函数调用的值称为实参

参数分类 (按定义)

  • 必选参数 => 在调用时必须要填
  • 默认参数 => 提供默认值,调用时可填可不填
  • 可变位置参数
  • 可变长关键字参数

参数分类 (按调用)

  • 位置参数 => 按参数顺序依次传递

  • 关键字参数 => 按key依次传递

  • # 调用的角度
    # def sum(a, b):pass
    # sum(1,2)      => 位置参数 => 按顺序依次传递
    # sum(b=2, a=1) => 关键参数传递 => key:value
    

(1)缺省参数

  • 调用函数时,缺省参数的值如果没有传入,则取默认值

  • # 为什么要使用默认参数 => 让用户调用的时候更简洁
    def myinfo(name, age, sex="保密"):
        print(name, age, sex)
    
    # 位置参数方式调用
    myinfo('cali', 18, "男")
    myinfo('cali', 18)
    # NO => age没有
    # myinfo(name='cali', sex="男")
    # 关键字参数方式调用
    myinfo(name="cali", age=18)
    
    cali 18 男
    cali 18 保密
    cali 18 保密
    
  • 注意

    带有默认值的参数一定要位于参数列表的最后面,否者会报错

(2)可变长位置参数

  • 有时可能需要一个函数能处理比当初声明时更多的参数, 这些参数叫做不定长参数,声明时不会命名。

  • def mysum(*args):
        # print(args)
        sum = 0
        for item in args:
            sum += item
        print(sum)
    mysum(1, 2, 3, 4, 5)
    
    15
    

(3)可变长关键字参数

  • def mysum(**kwargs):
        print(kwargs)
        sum = 0
        for value in kwargs.values():
            sum += value
        print(sum)
    
    mysum(a=1, b=2, c=3, d=4)
    
    15
    

(4)总结

参数定义的先后

  • 最佳方式:mysun(必选参数, *args, 默认参数, **kargs)
  • 不是每项都需要,如果需要的话,要按上述顺序

参数的调用

  • mysum(位置参数,关键字参数)

三、函数的return语句

  • 所谓“返回值”,就是程序中函数完成一件事情后,最后给调用者的结果
  • 一个函数中可以有多个return语句,但是只要有一个return语句被执行到,那么这个函数就会结束了,因此后面的return没有什么用处
# 没有return 语句时,默认返回 None
def mysun(b, a=10):
    pass
print(mysun(10))

#None
# return => 返回函数结果
# 函数如果没有return语句,返回的是None
# 退出函数并返回结果

# return可以直接退出函数
def mysum():
    for i in range(10):
        print(i)
        # return
        return None
    print(2)
    print(3)
    print(1)
    print(1)
    print(1)

mysum()

#0

函数中包含多个return语句

def mysum(x):
    if x%2:
        return "奇数"
    else:
        return "偶数"

for x in range(4):
    print(mysum(x))
偶数
奇数
偶数
奇数

函数返回多个值

def myfun(*args):
    sum = 0
    for item in args:
        sum+=item
    return len(args), sum

result = myfun(1,2,3,4,5)
print(result)
count, sum = myfun(1,2,3,4,5)
print(count, sum)
(5, 15)
5 15

四、匿名函数

匿名函数的定义:

img

什么时候使用匿名函数

  • 当函数只是实现非常简单并且一次性使用时,可以定义为匿名函数
  • 当我们在传入函数时,不需要显式地定义函数,直接传入匿名函数更方便。
# 匿名函数的参数,匿名函数是默认返回的,不需要再加return
func03 = lambda x: x ** 3  # 传递一个x,然后给x三次方,并返回
print(func03(2))  # 打印2的三次方

func04 = lambda x, y: x + y  # 传递一个x和y,然后给相加,并返回
print(func04(3,5))# 打印3+5
8
8
# sorted => 内建函数 => 排序
# sorted(要排序的对象,key=函数)
help(sorted)

mylist = [-1, 10, 8, -9, 6, 3]
#降序排列
print(sorted(mylist,reverse=True))

#升序排列
print(sorted(mylist,reverse=False))

# 按绝对值进行排序 (-1, 3, 6, 8, -9, 10)
print(sorted(mylist, key=lambda x:x if x>0 else -x))
# if x>0:
#     return x
# else:
#     return -x

# 不区分大小写排序
mystr = "AsdBcmG"
print(sorted(mystr, key=lambda x:x.lower() if x.isupper() else x))
print(sorted(mystr, key=lambda x:x.lower()))
[10, 8, 6, 3, -1, -9]
[-9, -1, 3, 6, 8, 10]
[-1, 3, 6, 8, -9, 10]
['A', 'B', 'c', 'd', 'G', 'm', 's']
['A', 'B', 'c', 'd', 'G', 'm', 's']

五、递归函数

实现递归的条件:

  • 出口条件,即递归“什么时候结束”,这个通常在递归函数的开始就写好
  • 可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式

通过例子来加强理解;

def fun01(n:int)->int:
    """
    :param n:输入一个正整数
    :return: 返回阶乘
    """
    if n == 1:
        return 1
    else:
        return n*fun01(n-1)

print(fun01(4))

#24
  • 递归限制
import sys
#获取最大递归次数
print(sys.setrecursionlimit())
#修改最大递归次数
sys.setrecursionlimit(9999999)

通过比较时间来看出 递归和循环之间的差异;

其中,递归的方式在调用的过程中一直在入栈。这是要耗费内存的,所以在参数值大到一定程度时,入栈 的数据太多就会导致栈溢出了。

import sys
import time
sys.setrecursionlimit(9999999)
def factorial1(n: int) -> int:
    if n == 1:
        return n
    else:
        return n * factorial1(n - 1)

n = 3000
# 获取开始时间
start = time.time()
# 递归
factorial1(n)
# 获取结束时间
cost = time.time() - start

print(cost)
0.003999233245849609
import sys
import time
sys.setrecursionlimit(9999999)
def factorial2(n: int) -> int:
    result = 1
    for i in range(1, n + 1):
        result = result * i
    return result

n = 3000
# 获取开始时间
start = time.time()
# 递归
factorial2(n)
# 获取结束时间
cost = time.time() - start

print(cost)
0.0020122528076171875

六、函数的参数传递

从动态类型看函数的参数传递, 函数的参数传递,本质上传递的是引用

1、传递不可变对象

def f(x):
    x = 100
    print("函数内的值:",x)

a = 1
f(a)
print("函数外的值:",a)
函数内的值: 100
函数外的值: 1
  • 总结

• 参数x是一个新的引用,指向a所指的对象。

• 如果参数是不可变(immutable)的对象,a和x引用之间相互独立。对参数x的操作不会影响引用a。

• 这样的传递类似于C语言中的值传递。

2、传递可变对象

def func1(a:list)->list:
    """
    :param a:接收一个list
    :return: 返回一个list
    """
    a.append(10)
    return a

a = [1,2,3]
print("没有做任何操作的列表:",a)
func1(a)
print("经过一次func1():",a)
func1(a)
print("经过二次func1():",a)
没有做任何操作的列表: [1, 2, 3]
经过一次func1(): [1, 2, 3, 10]
经过二次func1(): [1, 2, 3, 10, 10]
  • 总结

• 如果传递的是可变(mutable)的对象,那么改变函数参数,有可能改变原对象。

• 所有指向原对象的引用都会受影响,编程的时候要对此问题留心。

在定义参数时,尽量避免参数的默认值设置成一个可变对象

七、全局变量和局部变量

1、局部变量

局部变量,就是在函数内部定义的变量

def func01():
    # 申明一个局部变量x,此x只有这个函数中生效
    x = 10
    print("改变之后:",x)
x = 5
func01()
print("在函数外部:",x)
函数内部: 10
在函数外部: 5

小结

  • 其作用范围是这个函数内部,即只能在这个函数中使用,在函数的外部是不能使用的
  • 局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储
  • 当函数调用时,局部变量被创建,当函数调用完成后这个变量就不能够使用了

2、全局变量

如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,这样的变量就是全局变量

(1)全局变量
# 定义全局变量
a = 100

def test1():
    print(a)  # 虽然没有定义变量a但是依然可以获取其数据

def test2():
    print(a)  # 虽然没有定义变量a但是依然可以获取其数据

# 调用函数
test1()
test2()
100
100
(2)修改全局变量
def func01():
    global x
    print("改变之前:",x)
    # 申明x是全局变量,函数内部改变外部也会跟着一起改变
    x = 10
    print("改变之后:",x)
x = 5
func01()
print("函数外部:",x)
改变之前: 5
改变之后: 10
函数外部: 10

小结

  • 如果在函数中出现global 全局变量的名字 那么这个函数中即使出现和全局变量名相同的变量名 = 数据 也理解为对全局变量进行修改,而不是定义局部变量
  • 当函数内出现局部变量和全局变量相同名字时,函数内部中的 变量名 = 数据 此时理解为定义了一个局部变量,而不是修改全局变量的值。

八、文档注释

类型注解-typehint

1、实现类型检查,防止运行时出现的类型不符合情况。

2、作为文档附加属性,方便开发者调用时传入传出的参数类型。

3、提升 IDE 的检查机制,在智能提示时更快给出提示和类型检查结果。

# 文档注释:方便使用函数的人查看函数的功能
# arg1:int  => 说明参数期待的数据类型
# -> int    => 函数的返回的类型
def func01(arg1:int) -> int:
    """
    这个函数是用来测试的
    :param arg1: 一个int类型的数据
    :return: 返回2次方
    """
    try:
        return arg1**2
    except TypeError:
        return "你输入的有误!"

help(func01)
print(func01('a'))
print(func01(12))
Help on function func01 in module __main__:

func01(arg1: int) -> int
    这个函数是用来测试的
    :param arg1: 一个int类型的数据
    :return: 返回2次方

你输入的有误!
144

九、内建函数与工厂函数

img

img

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pod️

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值