函数基础和核心用法

本文深入探讨Python函数的应用与底层原理,包括函数分类、参数传递、作用域规则等内容,并介绍递归函数、内部函数及LEGB规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

五章—函数的应用和底层分析

函数是可重用的程序代码块。函数的作用,不仅可以实现代码的复用,更能实现代码的一致性。一致性指的是,只要修改函数的代码,则所有调用该函数的地方都能得到体现。

Python 函数的分类

(1)内置函数
我们前面使用的 str()、list()、len()等这些都是内置函数,可以拿来直接使用。
(2)标准库函数
我们可以通过 import 语句导入库,然后使用其中定义的函数
(3) 第三方库函数
Python 社区也提供了很多高质量的库。下载安装这些库后,也是通过 import 语句导入,然后可以使用这些第三方库的函数
(4)用户自定义函数
用户自己定义的函数,显然也是开发中适应用户自身需求定义的函数。今天我们学习的就是如何自定义函数.

形参和实参

在python函数中,在定义时写的 函数的标识符称为“形式参数”,简称“形参”。也就是说,形式参数是在定义函数时使用的。 形式参数的命名只要符合“标识符”命名规则即可。
在调用函数时,传递的参数称为“实际参数”,简称“实参”

help语句调用查看函数解释

调用 help(函数名.doc)可以打印输出函数的文档字符串

def print_star(n):
    '''根据传入的 n,打印多个星号'''
    print("*" * n)
help(print_star)

return语句
(1) 返回值
(2)结束函数运行

def x(a,b):
    print(a+b,"a和b的值")
    return(a+b) #返回值

def y(a,b):
    print(a)
    return  #结束运行 往后的程序并未运行
    print(b)

x(30,40)
y(50,60)

执行 def 定义函数后,系统就创建了相应的函数对象。对象可以看作堆里的内存块。因此函数同样可以想字符串赋值一样把它的功能赋给字符。

变量的作用域(全局变量和局部变量)

变量起作用的范围称为变量的作用域,不同作用域内同名变量之间互不影响。变量分为:全局变量、局部变量。

a=5  #全局变量
b=1
def Yan(a,b):
    a=10
    b=40  #局部变量
    print(a,b)

Yan(a,b) # 全部调用局部变量

如果在函数中的变量与函数外的全局变量重复则调用时,用的是局部变量,如想使用全局变量则使用global语句。

局部变量的查询和访问速度比全局变量快,优先考虑使用,尤其是在循环的时候

import math
import time

def Myfunc1():
    start=time.time()
    for i in range(1000000):
        math.sqrt(30)
    end=time.time()
    print(end-start)

def Myfunc2():
    start=time.time()
    b=math.sqrt
    for i in range(1000000):
        b(30)
    end=time.time()
    print(end-start)

Myfunc1()
Myfunc2()

参数的传递

所有的赋值操作都是“引用的赋值”。Python 中参数的传递都是“引用传递”,不是“值传递”。

传递参数是可变对象(例如:列表、字典、自定义的其他可变对象等),实际传递的是对象的引用。在函数体中不创建新的对象拷贝,而是可以直接修改所传递的对象。

# 传递可变对象的引用
a=[20,30]
print(id(a))
def fob(m):
    print('m:',id(m))
    m.append(40)
    print(id(m))

fob(a)
print('a:',id(a))
print(a)

传递参数是不可变对象(例如:int、float、字符串、元组、布尔值),实际传递的还是对象的引用。在”赋值操作”时,由于不可变对象无法修改,系统会新创建一个对象。

# 传递不可变对象的引用
a=100
print(id(a))
def fin(m):
    print(id(m))
    m=m+2
    print(id(m))
fin(a)
print(id(a))

浅拷贝和深拷贝

浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用。
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象

# 深copy和浅copy
import copy
a=[100,200,4,[1,5,6]]

b=copy.copy(a)
b.append(30)
b[3].append(7)
print(a)
print(b)
# 深copy和浅copy
import copy
a=[100,200,4,[1,5,6]]

b=copy.deepcopy(a)
b.append(30)
b[3].append(7)
print(a)
print(b)

传递不可变对象包含的子对象是可变的情况

a=(30,40,50,[5,6,7])
print('a:',id(a))
def myfunc2(m):
    print('m:',id(m))
    m[3][0]=567
    print('m:',id(m))
    print('m:',m)
myfunc2(a)
print(a)

函数中的参数分类

位置参数:函数调用时,实参默认按位置顺序传递,需要个数和形参匹配。按位置传递的参数。
默认值参数:可以为某些参数设置默认值,这样这些参数在传递时就是可选的。称为“默认值参数”。默认值参数放到位置参数后面
命名参数:可以按照形参的名称传递参数,称为“命名参数”,也称“关键字参数”

# 位置参数  默认值参数 命名参数
def myfunc01(a,b,c,d):
    print('{0}-{1}-{2}-{3}'.format(a,b,c,d))


def myfunc02(a, b, c=33, d=66):
    print('{0} - {1} - {2} - {3}'.format(a, b, c, d))

myfunc01(10,20,30,40)
myfunc02(10,2,3)
myfunc02(10,2)

可变参数指的是“可变数量的参数”。分两种情况:
(1)*param(一个星号),将多个参数收集到一个“元组”对象中。
(2)**param(两个星号),将多个参数收集到一个“字典”对象中。

强制命名参数:在带星号的“可变参数”后面增加新的参数,必须在调用的时候“强制命名参数”。

lambda 表达式可以用来声明匿名函数。lambda 函数实际生成了一个函数对象。

eval()函数

功能:将字符串 str 当成有效的表达式来求值并返回计算结果。

a="print('abcd')"
eval(a)
a=10
b=15
dict1=dict(a=12,b=13)
print(dict1)

c=eval('a+b',dict1) #若不加括号后面的dict1则默认执行前面赋值的a和b
print(c)

递归函数

递归函数指的是:自己调用自己的函数,在函数体内部直接或间接的自己调用自己。递归类似于大家中学数学学习过的“数学归纳法”。

# 测试递归函数的基本原理

def myfunc1():
    print('myfunc()')
    myfunc1()
myfunc1()  # 会无限循环

注意:该程序会无限循环,最终报错,没有终止条件。

# 测试递归函数的基本原理

def myfunc1(n):
    print('myfunc()',n)
    if n==0:
        print('over')
    else:
        myfunc1(n-1)
    print('myfunc1()*****',n)

myfunc1(5)  # 有终止条件会无限循环

递归函数由于会创建大量的函数对象、过量的消耗内存和运算能力。在处理大量数据时,谨慎使用。

练习递归函数求阶乘:

# 递归函数求阶乘
def myfunc1(n):
    if n==1:
        return 1
    else:
        return n*myfunc1(n-1)

s=myfunc1(6)
print(s)

嵌套函数(内部函数):在函数内部定义的函数

(1)封装 - 数据隐藏
外部无法访问“嵌套函数”。
(2)贯彻 DRY(Don’t Repeat Yourself) 原则
嵌套函数,可以让我们在函数内部避免重复代码。
(3)闭包

内部函数和外部函数之间关系的测试

#测试嵌套函数
def outmyfunc1():
    print('a=20')
    def innermyfunc1():
        print('b=30')
    innermyfunc1() #内部函数则需内部调用,若在外部调用则报错显示没有定义

outmyfunc1()

嵌套函数打印chinesenae和englishname的练习

def name(ischinesename,name,familyname): #ischinesename是个判断条件的参数用于内部函数的条件
    def innername(a,b):
        print('{0}{1}'.format(name,familyname))
    if ischinesename:
        print('{0}{1}'.format(familyname,name))
    else:
        print('{0}{1}'.format(name, familyname))
name(True,'邦','刘')

nonlocal语句

# 测试nonlocal语句
a=100
def myout():
    b=13
    print('b:',b)
    global a  #声明是全局变量,即是把全局变量更改了
    a=1000
    print('a:', a)
    def myinner():
        nonlocal b  #声明是非局部变量即是外层函数的b也更改了
        b=18
        print('b:',b)

    myinner()
myout()
print('a:',a)

LEGB规则

LEGB 规则
Python 在查找“名称”时,是按照 LEGB 规则查找的:
Local–>Enclosed–>Global–>Built in
Local 指的就是函数或者类的方法内部;
Enclosed 指的是嵌套函数(一个函数包裹另一个函数,闭包);
Global 指的是模块中的全局变量;
Built in 指的是 Python 为自己保留的特殊名称。

# LEGB规则测试程序
def outer():
    str='outer你好'
    def inner():
        str='inner你好'
        print(str)
    inner()
outer()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

1318_卜献宝

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

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

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

打赏作者

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

抵扣说明:

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

余额充值