python基础之---函数

python基础之—函数

文章目录

  • python基础之---函数
  • 一、基本用法
    • 函数的定义
  • 二、函数的调用
    • 1.基本用法
    • 2.位置传参
    • 3.关键字传参
    • 4.参数默认值
    • 5.可变位置参数
    • 6.可变关键词参数
    • 7. ∗ * 参数
    • 8.多参数解包
      • 1.使用 ∗ * 解包
      • 2.使用 ∗ ∗ ** 解包
  • 三、可变和不可变参数
    • 1.不可变类型
    • 2.可变类型
    • 3.操作可变数据
  • 四,匿名函数
  • 五,内置函数
    • all()
    • any()
    • sum()
    • sorted()
    • reversed()
    • callable()
    • zip()
    • eval()
    • exec()
    • globals()和locals()
    • filter()
  • 六,高阶函数
    • map
    • filter
    • reduce
  • 七,变量作用域
    • Local→局部作用域
    • Enclosing→嵌套作用域
    • Global→全局作用域
    • Built-in→内建作用域
    • 作用域---函数的调用
    • 作用域---修改变量的值
  • 八,函数内存分配
  • 九,递归函数


一、基本用法

  • 概念

    函数是可以重复执行的语句块,可以重复调用

  • 作用

    用于封装语句块,提高代码的重用性。

  • 定位
    函数是面向过程编程的最小单位

函数的定义

使用def 语句定义一个函数a

#函数
#定义一个函数
def kn1():
    print("kn1")
kn1()#运行函数内部的代码
kn1
def kn2(a,b):
    print(a+b)
kn2(1,2)

3

函数的返回值,return

#函数的返回值,return
def kn3(a,b):
    return a+b
re=kn3(1,2)
print(re)
3

二、函数的调用

1.基本用法

  • 函数名后面跟上 小括号() 表示函数的执行。
  • 函数调用是一个表达式,可以参与运算
  • 函数调用时传递参数的方式有多种,包括位置传参、关键词传参、多个参数解包、参数默认值等。

2.位置传参

最常见的传参方式,参数按定义的顺序依次传入函数。

  • 示例
#函数位置传参
#传入的实参的顺序与形参的顺序一一对应
def fn1(x1,x2):
    print("x1",x1)
    print("x2",x2)
fn1(1,2)
fn1(10,20) 
#fn1(1,2,3)参数一致,多了一个参数,报错,
#fn1(1)少了也报错

x1 1
x2 2
x1 10
x2 20
def fn2(x1,x2,x3):
   print(x1)
   re=x1+x2
   print(re)
fn2(1,2,3)#参数一致,但未使用,不影响函数执行
# fn2(1,2)#就算只使用了2个参数,的调用时也必须输入3个参数,否则报错、
1
3
2 1

3.关键字传参

通过指定参数的名称来传值,无顺序限制,代码可读性较高。

  • 示例
#关键字参数
def fn3(x1,x2):
    print(x1,x2)
    
fn3(x2=1,x1=2)#指定了名字可以不按顺序传入参数
fn3("hello",x2="world")
# fn3(x1="hello","world")#位置参数不能出现在关键字参数后面
2 1
hello world

4.参数默认值

定义函数时可为某些参数指定默认值,如果不传参则使用默认值。默认值参数必须位于无默认值参数的后面。

  • 示例
#参数默认值
def fn(a,b=1):
    print(a,b)
fn(1)
fn(1,2)

1 1
1 2
def fn(a,b=1,c=10):
    print(a,b,c)
fn(1,c=2)
fn(10,20,30)
1 1 2
10 20 30

5.可变位置参数

使用 ∗ a r g s *args args 可让函数接受任意数量的位置参数。 ∗ a r g s *args args 会将多余的位置参数收集成一个元组。

  • 示例
def fn(a,b,*args):
    print(a,b,args)
    for i in args:
        print(i)
fn(10,20,30,41,25,52)  
10 20 (30, 41, 25, 52)
30
41
25
52

6.可变关键词参数

使用 ∗ ∗ k w a r g s **kwargs kwargs 可以让函数接受任意数量的关键词参数。 ∗ ∗ k w a r g s **kwargs kwargs 会将多余的关键词参数收集成一个字典。

def fn(a,b,**arges):
    print(a,b,arges)
    for i in arges:
        print(i)
fn(1,2,name='张三',age=18)
1 2 {'name': '张三', 'age': 18}
name
age

7. ∗ * 参数

  • 参数本身不是一个参数,而是一个特殊用法,是一个占位符
#*参数
#*本身不是一个参数,而是一个特殊用法,是一个占位符,
#c必须是关键字参数
def fn(a,b,*,c):
    print(a,b,c)
fn(1,2,c=30)
1 2 30

8.多参数解包

1.使用 ∗ * 解包

def fn(a,b,c):
    print(a,b,c)

fn(1,2,3)

fn(*[1,2,3])
1 2 3
1 2 3

2.使用 ∗ ∗ ** 解包

def fn(a,b,c):
    print(a,b,c)

fn(1,2,3)

fn(**{'a':1,'b':2,'c':3})
1 2 3
1 2 3

三、可变和不可变参数

在 Python 中,实参可以是可变类型或不可变类型。它们的区别主要体现在值传递引用传递的行为上。

1.不可变类型

不可变类型包括: i n t 、 f l o a t 、 s t r 、 t u p l e 、 f r o z e n s e t int、float、str、tuple、frozenset intfloatstrtuplefrozenset 等。

传递方式是值传递: 传递给函数的是该对象的值,函数内部修改该值不会影响外部变量的值。

  • 示例
def fn(a):
    a=20
x=10
a=fn(x)
print(x)
10

2.可变类型

可变类型包括: l i s t 、 d i c t 、 s e t list、dict、set listdictset 等。这些类型的对象可以在原地修改。

传递方式是引用传递 :传递给函数的是对象的引用(即内存地址),在函数内部修改该参数的内容会直接影响外部变量。

  • 示例
def fn2(arr):#传入数据是可变数据,
    arr[0]=20
x=[1,2,3,4,5]
fn2(x)
print(x)

[20, 2, 3, 4, 5]

3.操作可变数据

通过复制对象来避免可变类型副作用:

  • 列表:使用 lst.copy() 或切片 lst[:] 来创建一个副本。
  • 字典:使用 dict.copy()copy.deepcopy() 来进行深拷贝。
  • 元组:推荐用tuple 创建新的元组,虽然本身就是不可变。

示例:

# 解决方案:如果传入一个可变数据 函数内部又想操作它 又不想改变外部传入的那个可变数据
def fn3(arr):
 arr=arr.copy()
 arr[0]=100
x=[10,20,30]
fn3(x)
[20, 20, 30]

四,匿名函数

匿名函数是没有名字的函数,通常用于需要一个简短的、临时的函数场景,它可以有任意数量的参数,但只能包含一个表达式,并返回该表达式的结果。

  • 语法
lambda arguments(参数): expression(表达式)
  • 优点
  1. 结构简单lambda 函数通常用在需要一个短小函数的地方,而普通函数则更适合复杂的逻辑。
  2. 匿名性lambda 函数是没有名字的,它们通常只在一个地方使用,并且不需要被重复调用。
  3. 功能限制lambda 函数只能包含一个表达式,不可以包含多行语句,而普通函数可以包含多行代码、条件判断、循环等复杂逻辑。
#匿名函数
fn = lambda x,y:x+y
print(fn(10,20))
30
fn2 = lambda x:"奇数"if x%2==1 else "偶数"
print(fn2(10))
偶数

五,内置函数

all()

如果可迭代对象中的所有元素都为 True,返回 True,否则返回 False

x=[10,20,30,0]
re=all(x)#x可迭代对象中的所有元素都判定True
print(re)
False

any()

传入的数据容器中的数据 只要有一个数据判定为true就返回true,否则返回false

x=[10,20,30,0]
any(x)#传入的数据容器中的数据 只要有一个数据判定为true就返回true,否则返回false
print(any(x))
True

sum()

返回可迭代对象中所有元素的总和。

x=[10,20,30,0]
sum(x)#传入的数据容器中的数据 求和
print(sum(x))
print(sum(x)/len(x))
60
15.0

sorted()

返回一个新列表,其中包含可迭代对象中的元素,按照升序排序。

x=[10,20,30,0]
sorted(x)#对传入的数据容器中的数据进行排序
print(sorted(x))
[0, 10, 20, 30]

按照中位数,或者平均数距离最近排序

#距离20最近的数字排前面
x=[-10,20,-30,0]
def fn(x):
   print(x)
   return (x-20)**2
re=sorted(x,key=fn)
print(re)
-10
20
-30
0
[20, 0, -10, -30]

reversed()

返回一个反向迭代器。

x=[10,22,65,54]
re=reversed(x)
re=list(re)
print(re)
[54,65,22,10]

callable()

检查对象是否可以被调用(即是否是函数或方法)。

#callable(x)
fn=100
fn=lambda x:x+1
re = callable(fn)
print(re)
fn(11)
True

zip()

将多个可迭代对象打包成一个元组,常用于并行遍历多个序列。

#zip(x,y) 把x和y合并成一个迭代器
x=[1,2,3,4,5]
y=[10,20,30,40,50]
re=zip(x,y)#允许x和y长度不一样,多出的就不输出
print(re)
print(list(re))


[(1, 10), (2, 20), (3, 30), (4, 40), (5, 50)]

eval()

将字符串作为有效的 Python 表达式来执行,并返回结果。

eval("字符串中的代码")把传入的字符串中的代码执行,并返回结果‘’

exec()

执行存储在字符串中的 Python 代码。

# exec("字符串中的代码")把传入的字符串中的代码执行
exec("print('hello')")
exec("for i in range(10):print(i)")

globals()和locals()

globals() 返回当前全局符号表(字典);
locals() 返回当前局部符号表(字典)。

#gelobals()和locals()
#gelobals()返回全局变量,locals()返回局部变量
x=100
y=200
def fn():
    x=300
    y=400
    print(globals())
    print(locals())
fn()
{'x': 300, 'y': 400}

filter()

从可迭代对象中过滤出符合条件的元素。


#filter(x,y)传入函数和迭代器,返回满足条件的迭代器
x1=[1,2,3,4,5,6,7,8,9,10]
x2=filter(lambda x:x%2==0,x1)
print(list(x2))
[2, 4, 6, 8, 10]

六,高阶函数

高阶函数是指可以接受一个或多个函数作为参数,或者返回一个函数作为结果的函数。

map

map(function, iterable)

  • 接受一个函数和一个可迭代对象
  • 将接受的函数应用到可迭代对象的每个元素上
  • 返回一个包含结果的迭代器
#map(x,y)传入函数和迭代器,返回迭代器
x1=[1,2,3,4,5,6,7,8,9,10]
x2=map(lambda x:x**2,x1)
print(list(x2))
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  • 使用自己的函数写一个实现map函数功能的函数
def mymap(fn,list):
    re=[]
    for i in list:
        re.append(fn(i))#
    return re
print(mymap(lambda x:x**2,[1,2,3,4,5]))
[1, 4, 9, 16, 25]

filter

filter(function, iterable)

  • 接受一个函数和一个可迭代对象
  • 用接受的函数来筛选出可迭代对象中满足条件的元素
  • 返回一个包含满足条件的元素的迭代器
x1=[1,2,3,4,5,6,7,8,9,10]
x2=filter(lambda x:x%2==0,x1)
print(list(x2))
[2, 4, 6, 8, 10]
  • 使用自己的函数写一个实现filter函数功能的函数
def myfilter(fn,list):
    re=[]
    for i in list:
        if fn(i):
            re.append(i)
    return re
print(myfilter(lambda x: x>2, [1,3,5,0]))  
[3, 5]

reduce

reduce(function, iterable[, initializer])

  • reduce函数接受一个函数和一个可迭代对象
  • 将接受的函数累积地应用到可迭代对象的元素上
  • 可选的 i n i t i a l i z e r initializer initializer 参数可以作为累积的初始值
from functools import reduce
x=[1,2,3,3,4]
def fn(a,b):
 print(a,b,)
 return a+b
re=reduce(fn,x)#a是上一次的返回值 b是当前值 re是最后一次fn调用的返回值
print(re)
1 2
3 3
6 3
9 4
13
  • 使用自己的函数写一个实现myreduce函数功能的函数
#自定义
def myreduce(fn,list):
    re=list[0]
    for i in list[1:]:
        re=fn(re,i)
    return re

#测试
x=[1,2,3,3,4]
def fn(a,b):
 print(a,b,)
 return a+b
re=myreduce(fn,x)
print(re)
1 2
3 3
6 3
9 4
13

七,变量作用域

变量的作用域(Scope)是指在程序中某个变量的有效范围,也就是在代码的哪个部分可以访问或修改该变量。作用域定义了变量的可见性和生命周期。

Python中的变量作用域遵循LEGB规则(Local, Enclosing, Global, Built-in),依次搜索变量的定义位置。
精解分析

# 变量的作用域(难点)
# 作用域 只针对函数 没有函数 就不谈作用域
# 函数内部可以访问函数内部和外部的变量  但是函数外部不能访问函数内部的变量
#变量在fn函数外面也能使用 fn函数里面也能使用 在别的函数里面也能使用 
# 一个变量它在哪些地方能够使用哪些地方 哪些地方就是它起作用的代码区域=>作用域
#放在代码的最外层的变量 就是全局变量 哪些都能访问
#在函数内部访问一个变量时  
# 如果是取值那么就在自己的局部作用域中访问 
# 没有就去外层作用域访问 外层没有就去外层的外层 直到全局没有 就报错
# 如果是存值:在自己的作用域中找  没找到就在当前作用域内部创建

Local→局部作用域

  • 指函数或方法内部定义的变量。

  • 仅在函数内部有效,函数外部无法访问。

  • 在函数调用时被创建,在函数调用后自动销毁。

  • 示例:

def fn():
    x=10
print(x)

Enclosing→嵌套作用域

  • 指外层函数中的变量,在内层函数中可访问,但不可修改。

  • 当一个函数嵌套在另一个函数内部时,外层函数的变量属于Enclosing作用域。

  • 示例:

def fg():
    a=100
    def fg2():
        a1=300
        a2=200
        a1=666#a1是存值 在自己的作用域中找  没找到就在当前作用域内部创建
        print(a,a1,a2)
        # re=b1   在函数内部访问一个变量时,如果是取值的话,会从当前作用域中找,如果找不到,
        # 就会从外部作用域中找,找不到会报错
        print(re)
    fg2()
fg()
100 666 200
13

Global→全局作用域

  • 指模块级别定义的变量,整个模块都可以访问。

  • 如果想在函数中修改全局变量,需要使用global关键字。

  • 示例:如何用一个变量来记录一个函数调用的次数

a=20
def fn():
    x=10
print(a)

Built-in→内建作用域

  • 包含Python内建的函数、异常和常量,如print(), len(), int, Exception等。

  • 这些变量可以在任何地方使用。

  • 示例:

print(len([1, 2, 3]))  # 使用内建函数len

作用域—函数的调用

  • 函数也是标识符 也是一种数据 也跟变量是一样的 关于作用域
b=[10,20,30,40,lambda x:x+1]
print(b[0])
b[4]()
# xxx[1][2](3)(1)[4]
  • 作用域-函数的调用
  • 函数调用在A作用域 函数定义在B作用域(可行)
  • 函数无论在哪个作用域中调用 一定是在它定义的作用域下执行代码
a=100
def fm():
    print(a)

def fn():
    a=200
    fm()
fn()


def t1():
    a=100
    def t2():
        print(a)
    return t2

a=200
re=t1()#re是一个数据(函数)
re()#执行函数
100
100

作用域—修改变量的值

  • 变量有作用域: 使用变量的代码范围
  • 使用: 获取值, 修改值
a=1
def fn():
    # print(a)#报错 因为在函数内部有a就不会去访问外部的a  但是 取值时如果这个变量还没有创建 就会报错
    a=2#赋值 这个变量在当前作用域中没有 就会创建
fn()
print(a)
a=10
def fn():
    global a#明确指定 a是全局变量的a
    print(a)
    a=20#会修改全局变量a的值
fn()
print(a)

a=10
def fn():
    a=20
    def fm():
        print(a)
    fm()
fn()


a=10
def fn():
    a=20
    def fm():
        global a
        print(a)
        a=30
    fm()
fn()
print(a)


a=10
def fn():
    a=20
    def fm():
        nonlocal a
        print(a)
        a=30
    fm()
    print(a)
fn()
print(a)
1
10
20
20
10
30
20
30
10

八,函数内存分配

  • 将函数的代码存储到代码区,函数体中的代码不执行。

  • 调用函数时,在内存中开辟空间(栈帧),存储函数内部定义的变量。

  • 函数调用后,栈帧立即被释放。

def func(a, b):
	a = 20
	b[0] = 20

a = 10
b = [10 ,10 ,20 ]
func(a, b)
print(a) # 10
print(b) # [20]
10
[20, 10, 20]

python基础之---函数_第1张图片

九,递归函数

递归是指函数直接或间接调用自身的过程。递归通常用于解决分解成相似子问题的复杂问题

  • 递归:先递进,再回归。
  • 函数的作用域
  • 外层作用域 定义的函数 可以在内层作用域中使用
  • 函数A在函数A外面定义 可以在A函数里面调用A函数
  • 函数的每一次调用是相互独立的 并且作用域是同关系
def fm():
    print("fm被调用了")
def fn():
    #在这里是fn函数内部  那fn函数外部的全局作用域 有哪些标识符?
    # 这里的代码可以访问a fm fn
    # print(a)
    # print(fm)
    # print(fn)
    # fm()
    print("fn被调用了")
    fn()
fn()
def fn(a):
    if a>=5:
        return 5
    else:
        return fn(a+1)
a=1 
re=fn(a) 
print(re)
5
# 求12的阶乘
def fm2(a):
    if a<=1:
        return 1
    else:
        return a*fm2(a-1)
re=fm2(5)
print(re)#
120
  • 伪代码分析
伪代码="""
伪代码 主要用于分析程序的执行过程
假设 大括号就是作用域

global->scoped{
    fn函数
    a=1
    re=fn函数执行后的结果
    fn(a)==>执行产生作用域
    fn(1)->scoped{
          a=1
          if a>=5:
              return 5
          else:
              return fn(a+1)->结果fn(2)
      }
    fn(2)->scoped{
        a=2
        if a>=5:
              return 5
        else:
              return fn(a+1)->结果fn(3)
    }
    fn(3)->scoped{
       a=3
       if a>=5:
              return 5
       else:
              return fn(a+1)->结果fn(4)
    }
    fn(4)->scoped{
        a=4
        if a>=5:
              return 5
        else:
              return fn(a+1)->结果fn(5)
    }
    fn(5)->scoped{
        a=5
        if a>=5:
              return 5-->结果5
        else:
              return fn(a+1)
    
    }

}
"""

你可能感兴趣的:(python,开发语言,人工智能)