第五章 函数

目录

第五章 函数

5.1 函数的概述

5.2 函数的定义和调用函数

5.3 函数的分类

5.4 函数的参数

5.4.1 位置参数

5.4.2 默认值参数

5.4.3 可变参数

5.4.4 关键字参数

5.4.5 命名关键字参数

5.4.6 参数的组合

5.5 局部变量和全局变量

5.6 函数运行原理

5.7 值传递和引用传递

5.8 匿名函数 ---- lambda表达式

5.9 偏函数

5.10 函数的递归

5.11 全局函数

第五章 函数

5.1 函数的概述

在python中定义函数的时候需要使用def关键字,依次写的函数的名称、函数参数、冒号、函数体,如果函数有返回值的话需要使用return关键字进行返回

5.2 函数的定义和调用函数

语法规则

 def 函数名称([函数的参数]):
   #缩进  函数体
   [return 函数的返回值]
 #创建一个求绝对值的函数
 def my_abs(x):
     if x >= 0:
         return x
     else:
         return -x
     
 print(my_abs(-99))

调用函数的时候使用函数的名称进行调用

总结:如果函数在执行过程中,一旦执行了return,函数就会把结果进行返回,那如果没有return,函数的返回值是None

 >>> def my_abs(x):
 ...     if x >= 0 :
 ...             return x
 ...     else:
 ...             return -x
 ...
 >>> my_abs(-99)
 99

函数在调用的过程中必须要注意的函数的参数类型和个数

 >>> my_abs("a")
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 2, in my_abs
 TypeError: '>=' not supported between instances of 'str' and 'int'
 >>> my_abs(-99,99)
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: my_abs() takes 1 positional argument but 2 were given

isinstance()

 #创建一个求绝对值的函数
 def my_abs(x):
     if not isinstance(x,(float,int)):
         raise TypeError("bad operand type")
     if x >= 0:
         return x
     else:
         return -x
     
 print(my_abs("a"))

函数也可以返回多个值

 import math
 def move(x,y,step,angle):
     nx = x + step + math.sin(angle)
     ny = y + step + math.cos(angle)
     return nx,ny
 # print(move(100,100,60,math.pi/6))
 x,y = move(100,100,60,math.pi/6)
 print(x,y)

函数可以返回多个值,但是返回的结果是一个元组类型

5.3 函数的分类

根据有无参数:有参函数 无参函数

根据有无返回值:有返回值函数 无返回值函数

定义者分类:系统自定义的函数(abs min max) 第三方定义的函数(公司、某个组织、个人自己定义)

5.4 函数的参数

函数的参数:位置参数、默认值参数、命名参数、可变参数、万能参数

 #计算圆的周长
 def get_circle_cal(r,pi):
     return 2*pi*r
 ​
 # r = eval(input("请输入圆的半径"))
 # cal = get_circle_cal(r,3.14)
 # print("半径是{}的圆的周长是{}".format(r,cal))
 ​
 if __name__ == "__main__":
     r = eval(input("请输入圆的半径"))
     cal = get_circle_cal(r,3.14)
     print("半径是{}的圆的周长是{}".format(r,cal))

总结:python中代码的入口不是main函数

python是一门脚本语言,从上到下的顺序执行

main作用:写在main函数中的代码不会被导入到其他模块中

5.4.1 位置参数
def get_circle_cal(r,pi):      
    return 2*pi*r

def power(x):
    return x*x

def power1(x,n):
    return x ** n
5.4.2 默认值参数
def power1(x,n=2):
    return x ** n

print(power1(3,3))
print(power1(3))

注意:位置参数必须在前,默认值参数必须在后

如何这个函数有多个默认值参数,变化较小写在后面,变化较大的写在前面

def enroll(name,gender,age=18,city="重庆"):
    print("name",name)
    print("gender",gender)
    print("age",age)
    print("city",city)

# enroll("张三","男")
# enroll("李四","男",17)
print(enroll("李四","男",17))
def add_list(L=[]):
    L.append("END")
    return L
print(add_list([1,2,3,4]))
print(add_list([1,2,3,4]))
print(add_list([1,2,3,4]))
print(add_list([1,2,3,4]))
def add_list(L=[]):
    L.append("END")
    return L

print(add_list())
print(add_list())
print(add_list())
print(add_list())
print(add_list())

运行结果:

['END']
['END', 'END']
['END', 'END', 'END']
['END', 'END', 'END', 'END']
['END', 'END', 'END', 'END', 'END']

因为L指向的[] ---- 可变对象

注意:设置默认值参数的时候一定要指向一个不可变对象

不可变对象 ---- None

def add_list(L=None):
    if L is None:
        L = []
    L.append("END")
    return L

print(add_list())
print(add_list())
print(add_list())
print(add_list())
5.4.3 可变参数

可变参数是用*来表示的

可以传递实际的参数,或者可以不传递参数,可以传递0个、1个........ 任意个参数,底层是用元组的形式将参数进行封装起来

def calc(numbers):
    sum = 0 
    for i in numbers:
        sum = sum + i * i
    return sum

print(calc([1,2,3,4,5]))

print(calc((1,2,3,4,5)))
def calc(*numbers):
    sum = 0 
    for i in numbers:
        sum = sum + i * i
    return sum

print(calc(1,2,3,4,5))
print(calc(1))
print(calc())
def calc(*numbers):
    sum = 0 
    for i in numbers:
        sum = sum + i * i
    return sum

list = [1,2,3,4,5]
print(calc(list[0],list[1],list[2],list[3],list[4]))
print(calc(*list))
5.4.4 关键字参数

关键字参数也可以传递0个、1个或者任意个参数,它的底层是将参数封装成一个dict

def person(name,age,**kw):
    print("name:",name,"age:",age,"kw:",kw)

person("张三",18)
person("李四",20,city="重庆",gender="男")
dict = {"gender":"女","city":"北京"}
person("王五",20,**dict)
5.4.5 命名关键字参数
def person(name,age,**kw):
    if "gender" in kw:
        pass
    elif "city" in kw:
        pass
    print("name:",name,"age:",age,"kw:",kw)

需求:只能传入gender和city这两个参数,其他参数不能传入

def person(name,age,*,gender,city):
    print("name:",name,"age:",age,"gender:",gender,"city:",city)

# person("张三",20,job="XXX工程师")
person("张三",20,gender="男",city="重庆")

命名关键字参数可以取默认值

def person(name,age,*,gender,city="重庆"):
    print("name:",name,"age:",age,"gender:",gender,"city:",city)

person("张三",20,gender="男")
5.4.6 参数的组合

可以存在同一个函数中,但是一定有顺序

顺序:位置参数 默认值参数 可变参数 命名关键字参数 关键字参数

def f1(a,b,c=0,*args,**kw):
    print("a=",a,"b=",b,"c=",c,"args=",args,"kw=",kw)

def f2(a,b,c=0,*,d,**kw):
    print("a=",a,"b=",b,"c=",c,"d=",d,"kw=",kw)


f1(1,2,c=3)
f1(1,2,3,"a","b")
f1(1,2,3,"a",X=99)
f2(1,2,3,d=99,x=88)
a= 1 b= 2 c= 3 args= () kw= {}
a= 1 b= 2 c= 3 args= ('a', 'b') kw= {}
a= 1 b= 2 c= 3 args= ('a',) kw= {'X': 99}
a= 1 b= 2 c= 3 d= 99 kw= {'x': 88}
def f1(a,b,c=0,*args,**kw):
    print("a=",a,"b=",b,"c=",c,"args=",args,"kw=",kw)

def f2(a,b,c=0,*,d,**kw):
    print("a=",a,"b=",b,"c=",c,"d=",d,"kw=",kw)


# f1(1,2,c=3)
# f1(1,2,3,"a","b")
# f1(1,2,3,"a",X=99)
# f2(1,2,3,d=99,x=88)
args = (1,2,3,4)
kw = {"d":99,"x":88}
f1(*args,**kw)
args1 = (1,2,3)
kw1 = {"d":99,"x":88}
f2(*args1,**kw1)
a= 1 b= 2 c= 3 args= (4,) kw= {'d': 99, 'x': 88}
a= 1 b= 2 c= 3 d= 99 kw= {'x': 88}

5.5 局部变量和全局变量

全局变量:

在python中,定义在py文件中的变量称为全局变量

特点:代码运行的过程中始终有效(不会被垃圾回收机制回收,除非手动的回收)

name = "张三" #name就是全局变量
name = None

局部变量:

定义在函数中的变量称为局部变量,当函数被垃圾回收机制回收的时候,局部变量也会被回收

局部变量的作用域仅限于函数的内部,在函数的外部是不能访问的,会报错

name = "张三" #name就是全局变量
# name = None
age = 18
def show(msg):
    gender = "男" #局部变量
    print(msg)
    print(gender)
    print(name)  #在函数的内部是可以访问全局变量的
    print(age)

# print(show("哈哈哈哈哈哈哈"))
show("哈哈哈哈")
# print(gender)

总结:函数的外面不能访问函数内部定义的变量(局部变量)

反过来说,函数的内部是可以访问函数外的变量(全局变量),但是不能改变全局变量,如果非要去改变(操作)全局变量的话,需要借助global关键字

name = "张三" #name就是全局变量
# name = None
age = 18
def show(msg):
    gender = "男" #局部变量
    global age
    print(msg)
    print(gender)
    print(name)  #在函数的内部是可以访问全局变量的
    print(age)
    age += 1
    print(age)

# print(show("哈哈哈哈哈哈哈"))
show("哈哈哈哈")
# print(gender)

5.6 函数运行原理

为什么函数的内部不能去操作全局变量

函数是对象 ---- 对象存储在堆内存中

函数的调用的过程中,是一个压栈的过程,当函数调用完成之后,就会有弹栈的过程,弹栈之后就会被垃圾回收机制回收

5.7 值传递和引用传递

值传递:传递的是值

x,y之间是不冲突的,因为add(x,y)中的x和y是局部变量(形参),而后面输入的Input的x和y是实参,将实参传递给了形参

引用传递:传递的是对象

def info(fn,msg):
    fn()
    print(msg)

def print_msg():
    print("哈哈哈哈哈哈哈")

print(print_msg) #打印的是函数在内存中存储的内存地址  print_msg指的是函数本身
print(print_msg()) #None 因为函数没有返回值
def info(fn,msg):
    fn()
    print(msg)

def print_msg():
    print("哈哈哈哈哈哈哈")

# print(print_msg) #打印的是函数在内存中存储的内存地址  print_msg指的是函数本身
# print(print_msg()) #None 因为函数没有返回值
#引用传递
info(print_msg,"呵呵呵呵呵呵呵呵呵")

5.8 匿名函数 ---- lambda表达式

匿名函数:没有名字的函数,在python中是使用lambda这个表达式进行实现

function 函数名称(函数参数){
    函数体
    代码块
    return 返回值
}
function (函数参数){
    函数体
    代码块
    return 返回值
}
def 函数的名称([函数的参数]):
	#缩进   代码块  函数体
    return 函数的返回值

def ([函数的参数]):
	#缩进   代码块  函数体
    return 函数的返回值
             ------- 不支持的

匿名函数函数:

lambda 参数 :函数体 如果函数有返回值进行返回,如果没有就不用返回

def sum_abc(a,b,c):
    return a+b+c

print(sum_abc(10,20,30))
sum_lambda = lambda a,b,c : a+b+c
print(sum_lambda(10,20,30))

无参的匿名函数

lambda_a = lambda : 100
print(lambda_a())
print(lambda_a)

一个参数:

lambda_b = lambda num : num * 10
print(lambda_b(10))

多个参数:

sum_lambda = lambda a,b,c : a+b+c
print(sum_lambda(10,20,30))

包含表达式:

lambda_c = lambda x : x if x % 2 == 0 else x + 1
print(lambda_c(6))
print(lambda_c(7))

总结:匿名函数是使用lambda表达式进行实现的,可以传入0个参数、1个参数、任意个参数,甚至可以包含表达式,但是函数返回值只有一个

lambda也可以作为一个参数进行传递

def sub_func(a,b,func):
    print("a=",a)
    print("b=",b)
    print("a-b=",func(a,b))

sub_func(100,1,lambda a,b : a - b )  # func = lambda a,b : a - b   func(a,b)

lambda作为函数的返回值

def run_func(a,b):
    return lambda c : a+b+c

return_func = run_func(1,1000)      # return_func = lambda c : 1+1000+c
print(return_func)
print(return_func(100))

5.9 偏函数

在python中,有时候我们需要调用某个函数的时候,如果将该函数的某个参数固定成某个值,可以使用偏函数

python中functools模块中,有一个方法就是偏函数 partial()

import functools

functools.partial()

from functools import partial ------ 只导入partial

>>> int("1234")
1234
>>> help(int)
Help on class int in module builtins:

class int(object)
 |  int([x]) -> integer
 |  int(x, base=10) -> integer
 |
 |  Convert a number or string to an integer, or return 0 if no arguments
 |  are given.  If x is a number, return x.__int__().  For floating point
 |  numbers, this truncates towards zero.
 |
>>> int("1234",base=8)
668
>>> int("1234",base=16)
4660
>>> def int2(x,base=2):
...     return int(x,base)
...
>>> int2("11001100")
204
>>> int2("0010")
2
>>> import functools
>>> dir(functools)
['GenericAlias', 'RLock', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', '_CacheInfo', '_HashedSeq', '_NOT_FOUND', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_c3_merge', '_c3_mro', '_compose_mro', '_convert', '_find_impl', '_ge_from_gt', '_ge_from_le', '_ge_from_lt', '_gt_from_ge', '_gt_from_le', '_gt_from_lt', '_initial_missing', '_le_from_ge', '_le_from_gt', '_le_from_lt', '_lru_cache_wrapper', '_lt_from_ge', '_lt_from_gt', '_lt_from_le', '_make_key', '_unwrap_partial', 'cache', 'cached_property', 'cmp_to_key', 'get_cache_token', 'lru_cache', 'namedtuple', 'partial', 'partialmethod', 'recursive_repr', 'reduce', 'singledispatch', 'singledispatchmethod', 'total_ordering', 'update_wrapper', 'wraps']
>>> functools.partial(int,base=2)
functools.partial(<class 'int'>, base=2)
>>> int3 = functools.partial(int,base=2)
>>> int3("11001100")
204

偏函数的作用但是将函数某个参数固定住(取一个默认值)

>>> int3("11001100",base=10)
11001100
>>> int3("11001100",base=8)
2359872
>>> int3("11001100",base=16)
285217024
>>> kw = {"base":10}
>>> int3("1100",**kw)
1100

5.10 函数的递归

在函数的内部可以调用其他的函数,但是如果在函数的内部调用函数自己,就是函数的递归

前提条件:

1、函数自己调用自己

2、要有终止条件

需求1:求n!

n*(n-1)*(n-1)*.......*2*1

函数+循环

def fact(n):
    sum = 1
    for i in range(1,n+1):
        # sum = sum * i
        sum *= i

    return sum
print(fact(5))
def fact_recursion(n):
    if n == 1:
        return 1
    return n*fact_recursion(n-1)

print(fact_recursion(5))
fact_recursion(5)
5 * fact_recursion(5-1)
5 * 4 * fact_recursion(4-1)
5 * 4 * 3 * fact_recursion(3-1)
5 * 4 * 3 * 2 * fact_recursion(2-1)
5 * 4 * 3 * 2 * 1

需求2:求斐波那契数列的第n项

0 1 1 2 3 5 8 13 21 .........

def fabonaci(n):
    first,second = 0,1
    for i in range(2,n+1):
        first,second = second,first+second
    return first

print(fabonaci(5))
print(fabonaci(6))
print(fabonaci(7))

ls = []
def fabonaci(n):
    first,second = 0,1
    for i in range(1,n+1):
        ls.append(first)
        first,second = second,first+second
    return ls
print(fabonaci(5))
def fabonaci_recursion(n):
    if n == 1:
        return 0
    elif n == 2:
        return 1
    return fabonaci_recursion(n-1)+fabonaci_recursion(n-2)

print(fabonaci_recursion(5))
print(fabonaci_recursion(6))
print(fabonaci_recursion(7))

所有的递归都可以用循环来实现,递归是一种特殊的循环

print(fact_recursion(1000))

递归会存在栈溢出的问题 -------- 尾递归 对递归方式进行了优化

尾递归:在函数返回的时候自己调用自己,返回值不能包含表达式

def func(n):
    return func_dict(n,1)
def func_dict(num,product):
    if num == 1:
        return product
    return func_dict(num-1,num*product)

print(func(5))
func(5)     
func_dict(5,1)
func_dict(5-1,5*1)
func_dict(4-1,4*5*1)
func_dict(3-1,3*4*5*1)
func_dict(2-1,2*3*4*5*1)
2*3*4*5*1 

5.11 全局函数

Python内置函数网站:内置函数 — Python 3.12.4 文档

round() ----- 四舍五入 ,对于奇数来说是标准的四舍五入,但是对于偶数来说小于等于5的都舍去

 >>> round(4.5)
 4
 >>> round(4.6)
 5
 >>> round(4.4)
 4
 >>> round(5.4)
 5
 >>> round(5.5)
 6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

璀云霄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值