python 笔记-函数

函数

内置函数

列举一些

round()

语法:

x:一个float数
n:返回小数位数

round(x,n)

abs(x) 返回数值x的绝对值

chr(x) 返回数值x 对应的ASCII码

dir(object)返回object对象的所有属性信息

divmod(a,b) 计算 a除以b 以元组形式返回 商和余数


自定义函数

语法

1、使用关键字 def
2、函数名必须以字母和下划线开头,不能使用python关键字
3、函数体缩进
4、包含关键字 return,代表函数有返回值;反之,代表返回None

def 函数名(参数1,参数2...):
    '''
    函数功能说明:
    实现什么功能、
    参数的数据结构和含义,
    返回值的数据结构等
    '''
    code

函数参数

形参

函数定义的参数

实参

函数调用时传入的参数,有实际的值

必选参数(位置参数)

必须填写的参数,在调用函数时实参的顺序与定义的顺序一致

示例:


def test(name,age):
    print(f"my name is {name};i am {age} years old.")
test('nebula',20)


运行结果:

my name is nebula;i am 20 years old.

如果调用时将参数位置调换:

test(20,'nebula')

运行结果:

my name is 2;i am nebula years old.

如果少传递一个参数,系统会抛出异常:

TypeError: test() missing 1 required positional argument: 'age'

默认参数

每次调用函数,如果一个参数传的值都是固定的,可以将参数值设置为默认参数,之后调用如果传了新的值就使用新的值,如果不传这个参数,函数会使用它的默认值进行操作;

规则

1、默认参数必须有具体的值 如:age=21
2、默认参数的位置必须在必选参数后
3、调用函数时,传参遵循定义时的顺序

示例 1
设置默认参数 age=50,调用时不传age


def test(name,age=50):
    print(f"my name is {name};i am {age} years old.")
test('Lily')


运行结果:

my name is Lily;i am 50 years old.

示例 2
调用时传一个新的值

def test(name,age=50):
    print(f"my name is {name};i am {age} years old.")
test('Lily',30)
my name is Lily;i am 30 years old.

关键字参数

在函数调用时明确参数名称并赋值。这样就可以不遵循定义的传参顺序。
就像去教室送信,位置参数必须按照定义的顺序才能找到对应的人;而如果在去之前就明确这封信我要给a,那封信我要给b.那么顺序就无所谓了

规则

1、调用时所有参数都采用关键字方式传递,不用考虑传递顺序
2、如果与固定参数方式混用,就只能按照定义的顺序传参
示例:

def test(name,gender,age):
    print(f"my name is {name};i am {age} years old.my gender is {gender}")
    
test(age=24,gender=0,name='page')

my name is page;i am 24 years old.my gender is 0

可变参数

在定义函数时无需明确参数名称, 调用时可以根据实际需要设置参数值添加到序列中,在将这个序列传入函数
主要有两种类型:

参数列表(元组)

参数列表:是把多个参数的参数值放在一个列表里,再将整个列表传入函数中

规则

1、args是参数列表
2、定义时和调用时都要在 args 前加上“*”号
3、在函数体中使用args 不用加 * 号
4、参数列表的每个元素只有值,没有参数名称

示例:

def change(*args):
    result="-".join(args)
    print(result)
args=('test','develop','product')
change(*args)
test-develop-product

参数字典

参数字典:是把每个参数以键值对的格式写入字典,每个键值对的键代表参数名称,每个键值对的值代表参数值

规则

1、kwargs 是 参数字典
2、定义和调用时都要在 kwargs 前添加 **
3、每个键值对代表一个参数,键 代表 参数名称 ,键值 代表 参数值

示例

def test(**kwargs):
    argname='-'.join(kwargs.keys())
    argvalue='-'.join(kwargs.values())
    print(f"参数字典的参数名称有 {argname}.")
    print(f"参数字典的参数值有 {argvalue}.")
kwargs={'name':'lily','age':'14','address':'sichuan'}
test(**kwargs)
参数字典的参数名称有 name-age-address.
参数字典的参数值有 lily-14-sichuan.

混用参数需要遵循的排序规则

必选参数→默认参数→可变参数(参数列表)→可变参数(参数字典)

关键字参数和可变参数不可混用

def test(name,age,*args,**kwargs):
    print(f"name:{name}")
    print(f"age:{age}")
    print(f"args:{args}")
    print(f"kwargs:{kwargs}")
name='nebula'
age='13'
args=["test","wand","andy"]
kwargs={"school":"middle","class":"three","profesion":"testing"}

test(name=name,age=age,*args,**kwargs)

运行结果

TypeError: test() got multiple values for argument 'name'

设置数据类型

对必选参数可以设置参数的数据类型
参数名称后加冒号 后跟数据类型

示例

def test(name:int):
    result=name+3+5
    print(result)
test('123')
TypeError: can only concatenate str (not "int") to str

如果参数的类型对函数对函数执行没有影响,那么传错误的类型,程序也能运行。但上面这个例子不行,所以报错了

函数返回值

函数的返回值是函数执行后的结果,给函数外部的程序使用
可以通过return 和yield 关键字实现

return关键字

返回结果的同时,中断函数的执行

def test1():
    for i in range(5):
        return i
re1=test1()
print(re1)
0

yield 关键字

返回结果并不中断函数的执行 ,可以说返回的是一个可迭代的对象 返回的数据类型: generator

def test2():
    for i in range(5):
        yield i

re2=test2()
for i in re2:
    print(i)
1234

定义函数返回值的数据类型

语法:
限定返回值的类型为str

def test() -> int:
    return 2+2
res=test()
print(res)
print(f"返回值的类型为:{type(res)}")  
4
返回值的类型为:<class 'int'>

如果实际返回值与定义不一样,程序仍然能运行,编辑器上也没有给警告。

函数调用过程

程序先通过括号确定语句是执行一个函数,再根据函数名称去找指定的函数并执行

变量的作用域

作用域范围

一个变量的作用域总是由在代码中被赋值的地方所决定


global_var = 0 #全局作用域
def outer():
    enclosing_var = 1 #闭包函数外的函数中
        def inner():
            local_var = 2 #局部作用域

LOCAL: 函数中定义的变量拥有局部作用域,

def fun1():
    name='nebula'
    print(f"嗨,我是fun1.我的名字是{name}")
    
name="test"
fun1()
嗨,我是fun1.我的名字是nebula

ENCLOSING 嵌套的父级函数的作用域

Global: 模块级别定义的变量 拥有全局作用域

Build In : 系统固定模块中的变量

作用域产生:

只有模块、类、函数会产生新的作用域,其他代码不会

变量查找优先级:

变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>python内置作用域

  • 当内部作用域修改全局变量,需要使用global关键字声明
    【 注意,在使用 global 关键字修饰变量名时,不能直接给变量赋初值,否则会引发语法错误】
cat='两只耳朵'
def fun1():
    global cat
    cat='四条腿'
    print(cat)
fun1()

运行结果:

四条腿
  • 局部作用域修改嵌套作用域的变量,需要使用nonlocal关键字声明
def fun1():
    a=5
    print(a)  
    def fun2():
        nonlocal a
        a=3
        print(a*4)
    fun2()
fun1()
5
12

闭包

一个内嵌函数被当做对象返回时,并且引用了外部变量,就形成了闭包

创建闭包的条件

  • 存在内嵌函数
  • 内嵌函数引用了外部变量
  • 外部函数的返回值是 内嵌函数
def callme():
    name='nebula'
    def mynum():
        print(f"call {name} it's time to go home!")
    return mynum
now=callme()
now()

结果:

call nebula it's time to go home!

还有关于装饰器的学习。。。。后面遇到再补充。现在学得还不够深入
[a ]https://zhuanlan.zhihu.com/p/59968665
https://blog.csdn.net/geekleee/article/details/73555951

递归函数

定义:在函数中循环调用这个函数本身,这个函数就称为递归函数
优点:定义简单,代码量少,逻辑清晰
缺点:影响性能,栈溢出

示例 不使用递归

#不使用递归的方式
def thesum(n):
     total=0
    for i in range(n+1):
    total +=i
     return total
 test=thesum(5)
 print(test)
15

递归

def thesum(n):
    if n<=0:
        return 0
    return n+thesum(n-1)
print(thesum(5))
15

计算过程:
n=5,
return 5+thesum(5-1), 循环向下执行函数
函数thesum(5-1)要等待thesum(4-1)的结果
thesum(4-1)又要等待 thesum(3-1)的结果
thesum(3-1)要等待 thesum(2-1)的结果
thesum(2-1) 等待thesum(1-1)的结果
根据 if 条件,此时thesum(1-1)的值为0
向上返回结果:
thesum(1-1)=0
thesum(2-1)=1
thesum(3-1)=3
thesum(4-1)=6
thesum(5-1)=10
最后 return 5+10

一层层往下,每往下一层都能得到一个结果,再一层层向上返回,得到最终的结果

再来一个例子

有4个人,每个人比自己后面的人大2岁,最后那个人是40岁,问第一个人几岁

def ages(n):
    if n == 1:
        return 40
    return ages(n-1)+2
ages(4)

结果为

46

尾递归函数

定义: 指在函数返回时调用函数本身,并且return语句 不包含表达式,这样,编译器或解释器就可以对尾递归进行优化,使递归本身无论调用多少次都只占用一个栈帧,不会出现栈溢出的情况

使用尾递归方法优化,可以解决递归函数栈溢出

尝试将上面的例子调整为尾递归函数
return语句要不包含表达式

def ages(n,age):
    if n==1:
        return age
    return ages(n-1,age+2)
print(ages(4,40))

46

匿名函数

语法

lambda 参数: 返回值

fun=lambda x,y:x*y
print(fun(4,5))

20

规则

  • 只能有一个表达式,且必须有返回值
  • 返回值不能使用 关键字return;会提示语法错误
  • 参数可有可无 ,也可以有多个。如果没有就不用填
  • 参数与返回值之间以冒号 : 相隔

优点

  • 精简代码,省去def函数定义的过程
  • 适用于 重复使用较少的函数或者命名不方便的情况
  • 某些时候使代码更容易理解

偏函数

Python自带的 functools 模块提供了一些常用的高阶函数,也就是用于处理其它函数的特殊函数。换言之,就是能使用该模块对可调用对象进行处理

偏函数 简单说就是对函数的二次封装,可以修改函数的默认值等,传参时可以少传

语法

fun2 = functools.partial(func, *args, **keywords)

第一个参数 func 指要封装的原函数
*args 和 ** keywords 代表要传入的必选参数和 关键字参数

from functools import partial
def fun(x,y):
    return x % y
print(fun(4,5))   #输出4
fun2=partial(fun,y=2)
print(fun2(4))  输出 0
posted @ 2021-12-10 15:30  深海鱼香茄子  阅读(82)  评论(0编辑  收藏  举报