Python 函数与高阶函数

原创
04/16 15:19
阅读数 29

一、函数概述

# -*- coding:utf-8 -*-

'''认识函数:
在一个完整的项目中,某些代码会被反复使用。那么将某段代码封装成函数,当我们要使用功能的时候直接调用函数即可
本质:函数是对功能的封装
有点:简化代码结构,增加代码的复用度
'''

'''定义函数
格式
def 函数名(参数列表):
    语句
    return 表达式

说明:
    def:函数代码块以def关键字开头
    函数名:遵守标识符的规则
    ():参数列表的开始和结束
    参数列表:是函数的调用者给函数的信息,多个信息之间用逗号分隔,如果没有信息,那么小括号中什么都不用写(注意此时小括号不能省略)(形参)
    冒号:函数的内容以冒号起始,并且锁紧
    语句:函数封装的功能
    return:一般用于结束函数,并返回给函数的调用者一些信息。“表达式”就是要返回的数据。如果没有显示的去写return语句,默认return回None
    
注意:
    定义函数时,程序是不会执行函数,当调用函数时才会执行
'''

# def gaolei(money):
#     pass


'''使用函数
格式:
函数名(参数列表)

说明:
    函数名:要使用某个功能函数的名字
    ():参数列表的开始和结束
    参数列表:调用者给函数的信息(实参)
    
函数调用的本质:实参给形参赋值的过程
'''

二、最简单的函数(无参无返回值)

# -*- coding:utf-8 -*-

#编写函数,实现在控制台上打印Martin is a good man的功能
def func():
    print("Martin is a good man")

#调用函数
func()

三、函数的参数

# -*- coding:utf-8 -*-

# 编写函数,给函数一个名字,一个年龄,一些爱好,在函数中进行打印
#  Martin  18    pwoer、money、book

#形式参数(形参):变量
#参数的数量理论上是无限制的,但是实际中最好不要超过6、7个,参数是类型没有限制
def func(name, age, hobby):
    print("%s is a good man! he is %d years old! he like %s、%s and %s"%(name, age, hobby[0], hobby[1], hobby[2]))

#函数在调用时,需要给函数按顺序传递数据,数量要对应
# 实际参数(实参):是值
func("Martin", 18, ["power", "money", "book"])

四、函数的返回值

# -*- coding:utf-8 -*-

# 编写函数,实现计算两个数的和
# 注意:在定义的函数体中,尽量不要常出现print和input
def func(x, y):
    sum = x + y
    return sum #将结果返回到调用函数的位置,返回的数据可以是任意类型的数据

# res接收了func函数运算后的返回值
res = func(1, 2)

五、传递参数

# -*- coding:utf-8 -*-


# 值传递:传递不可变类型数据
def func(num):
    print(id(num))
    num = 10
    print(id(num))

a = 20
print(id(a))
func(a)
print(a)




print("-------------------")
# 引用传递:传递可变类型数据
# 本质还是值传递,传递的是地址
def func2(arr):
    print(id(arr))
    arr.pop()
    print(id(arr))
    
li = [1,2,3,4,5]
print(id(li))
func2(li)
print(id(li))
print(li)

六、关键字参数

# -*- coding:utf-8 -*-



#目前为止的Python版本要求:函数调用时参数的顺序要与定义时一致
#关键字参数:允许函数调用时参数的顺序与定义时不一致


def func(name, age):
    print("%s is a good man! he is %d years old!"%(name, age))

#使用关键字参数
func(age=18, name="Martin")

七、默认参数

# -*- coding:utf-8 -*-

# 使用默认参数
# 在定义函数时尽量将默认参数写在最后
def func(name, age=18):
    print("%s is a good man! he is %d years old!"%(name, age))

# 在调用函数时,如果没有传递参数,就使用默认参数的值
func("Martin", 20)

八、不定长参数

# -*- coding:utf-8 -*-


#不定长参数:能处理比当初定义时更多的参数

# 在变量前加了星号,变量会存放所有未命名的变量的参数,如果在函数调用时没有指定参数,他就是个空元组
# 不定长参数在默认参数后面
# def func(name, age, a = 10, *args):
#     print("%s is a good man! he is %d years old"%(name, age))
#     print(args, type(args))
#
# func("Martin", 18)


#  **kwargs
#  **代表着键值对字典,和*差不多
# def func(name, age, **kwargs):
#     print("%s is a good man! he is %d years old"%(name, age))
#     print(kwargs, type(kwargs))
#
# func("Martin", 18, x=1, y=2, z=3)


def func(*args, **kwargs):
    print(args)
    print(kwargs)

func(1,2,3,x=1,y=2,z=3)


九、多个返回值

# -*- coding:utf-8 -*-


# 返回值可以一次性返回多个值
# 游戏中返回任务的坐标
def func():
    return 1,2

x, y = func()
z = func()
print(x, y)
print(z)
# for index, value in enumerate([1,2,3,4,5]):

十、函数也是一种数据

# -*- coding:utf-8 -*-
#函数也是一种数据
def func(x, y):
    return x + y

ret = func(1, 2)
print(ret)

f = func
print(f(2, 3))

十一、匿名函数

# -*- coding:utf-8 -*-



'''
概念:不在使用def语句这样标准的形式定义函数,使用lambda来创建匿名函数

特定:
    1、lambda只是一个表达式,函数体比def简单得多
    2、lambda主体是一个表达式而不是代码块,仅能在lambda表达式中封装有限的逻辑
    3、lambda函数拥有自己的命名空间,且不能访问自有参数序列之外或全局命名空间里的参数
    4、虽然lambda函数看起来只能写一行,却不同于c和c++的内联函数,后者的目的是调用小函数时不占用栈内存而增加运行效率

格式:
    lambda [arg1[, arg2[, arg3, ……]]]:expression


使用:作为参数传递,实现回调。简化代码
'''

f = lambda x, y: x + y
ret = f(5, 6)
print(ret)

​十二、map&reduce

# -*- coding:utf-8 -*-


'''
python 内建了map()和reduce()函数
'''

'''map(fn, lsd)
参数:
    fn:是一个函数
    lsd:集合
功能:将传输的函数fn依次作用到lsd集合中的每个元素,并把结果作为新的Iterator返回
'''
def chr2int(chr):
    return {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9}[chr]
ret = map(chr2int, "13586")
print(ret)
print(list(ret))


print("==============")
'''reduce(fn, lsd)
参数:
    fn:函数
    lsd:集合
功能:传入的fn函数作用在lsd集合中,这个fn函数必须接受两个参数,reduce把结果继续和序列的下一个元素作累计计算
    
    reduce(f, [a, b, c, d])==f(f(f(a,b),c),d)

'''
# 求一个序列的和
from functools import reduce
def func(x, y):
    return x + y
res = reduce(func, [1,2,3,4,5])
print(res)



#reduce配合map实现str2int
def str2int(s):
    def chrToint(chr):
        return {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9}[chr]
    def f(x, y):
        return x * 10 + y
    return reduce(f, map(chrToint, s))

res = str2int("13543")
print(res)
print(type(res))

十三、filter

# -*- coding:utf-8 -*-



'''
filter(fn, lsd)

参数:
    fn:函数
    lsd:集合

功能:用于过滤序列,把传入的fn函数依次作用在lsd集合中的每个元素上,然后根据返回值是True还是False决定是否保留该元素

'''

li1 = [1,2,3,4,5,6,7,8,9]
# 去掉列表中的所有偶数

#过滤的过程
# for i in li1:
#     if i % 2 == 0:
#         li1.remove(i)
# print(li1)

#过滤的逻辑
def func(num):
    if num % 2 == 0:
        return False
    return True
res = filter(func, li1)
print(li1)
print(res)
print(list(res))




print("==========")
#  找所有的素数



# 需求:删除列表中是空字符串的元素
li2 = ["a", "", "", "c", "    ", "  bsg  "]
print(li2)
def f(item):
    return item and item.strip()
res = filter(f, li2)
print(list(res))

十四、sorted

# -*- coding:utf-8 -*-


'''

排序算符:冒泡排序、快速排序、      选择排序、计数器排序……

'''
li = [3,4,1,2,5]


# 对列表进行排序
li1 = [3,4,1,2,5]
li2 = sorted(li1)
print(li2)

# 按绝对值大小排序
li3 = [3,-4,1,-2,5]
# key接收函数来实现自定义的排序
li4 = sorted(li3, key=abs)
print(li4)


#降序排序
li5 = [3,-4,1,-2,5]
li6 = sorted(li5, reverse=True)
print(li6)


# 字符串大小问题
# 原理:获取两个字符的第一个字符进行比较,谁的ASCII值大那么谁就大,如果相同则获取下一位字符比较
# print("abc">"ab")
li7 = ["abc", "awg", "agaerger", "eherth"]
#自定义排序逻辑
def func(x):
    return len(x)
li8 = sorted(li7, key=func)
print(li8)

十五、作用域

# -*- coding:utf-8 -*-

'''
作用域:变量可以使用的范围,程序的变量并不是在哪个位置都可以访问的,访问的权限决定于这个变量是在哪里赋值的。


作用域的划分:
    1、局部作用域(L)
    2、闭包函数外到函数中(E)
    3、全局作用域(G)
    4、内建作用域(B)

变量查找规则:
    L->E->G->B,首先在自身作用域中查找,找不到的话依次向上级作用中查找,注意不会向低级作用域中查找

Python中只有模块,类以及函数才会引入新的作用域,其它的代码块(比如if、elif、else、for、while、try、except等)是不会引入新的作用域的。

'''


十六、体现作用域

# -*- coding:utf-8 -*-
num = 5
#if不会引入新的作用域
if 1:
    index = 10
    print("num = %d"%num)

print("index = %d"%index)

def func(x, y):
    # 取值的使用
    print("在func中使用num:%d"%num)
    # 定义局部变量
    tmp = 100
    return x + y
print(func(1,2))
#在全局中使用局部变量,找不到的
# print("tmp = %d"%tmp)

十七、修改全局变量

# -*- coding:utf-8 -*-



num = 10
def func():
    # 在函数的内部可以直接获取全局变量的值,但是不能直接修改全局变量的值。直接修改相当于定义一个新的局部变量,没有修改到全局变量本身
    # 需要将定义的变量声明成全局变量
    global num
    print("1-----num = %d" % num)
    num = 2
    print("2-----num = %d" % num)

func()
print("3-----num = %d" % num)

十八、修改嵌套作用域中的变量

# -*- coding:utf-8 -*-
a = 30
def func():
    # 有global会在nonlocal那里报错,申明为全局的后就没有嵌套的了
    # global a
    # a = 10
    def f():
        #想修改嵌套作用域中的变量,需要将它声明
        # nonlocal a
        # a = 20
        print("1----a = %d"%a)
    f()
    print("2----a = %d"%a)

func()
print("3----a = %d"%a)

————————————————
版权声明:本文为【PythonJsGo】博主的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
博主主页:https://my.oschina.net/u/3375733

本篇文章同步在个人公众号:

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部