Python 极简核心:函数

本文详细介绍了Python中的函数,包括定义、参数传递、核心变量作用域以及高级特性如匿名函数lambda、嵌套函数、高阶函数、递归函数和闭包。闭包作为一种强大的工具,用于代码复用和减少函数参数。同时,文中探讨了装饰器函数的概念,它是闭包的一种应用,常用于函数的动态修饰。通过理解这些高级技巧,开发者能够更好地利用Python进行函数式编程。
摘要由CSDN通过智能技术生成

1. 函数

Python中有很多自带的函数,这里我们讨论的是一般意义上的函数,也就是自定义函数

1.1 定义

(1)函数
这里的函数跟数学意义上的函数并没有实质上的差异,由函数名参数函数体、和返回值几个组成。

函数的使用主要包括函数的建立函数的调用两个部分。

举个例子:

def add(a,b): # 函数名:add;参数传递:()必须有
    return a + b # 返回值,可以不写return(则默认为None)

print(add(1,1)) # 函数调用

2

(2)函数与类中的方法的区别:

方法也接受参数,处理、输出。但是它无法独立执行,需要有对象来调用执行。而且,方法在类中定义时总会有一个参数self,且这个参数在方法被实例对象调用时并不需要传递实参。这两点就是方法与函数的区别。


class My_module():
    '''
    country = 'China'  # 类属性——共性——静态(赋值)
    location = 'SH'    # 类属性——共性——静态(赋值)
    '''
    country = 'China'
    location = 'SH'
    def __init__(self, name, gender):
        '''
        :param name: 对象属性——个性——静态(借助 self 赋值)
        :param gender: 对象属性——个性——静态(借助 self 赋值)
        '''
        self.name = name
        self.gender = gender
    def say_hi(self, words):
        '''
        :param words: 方法——个性——动态(函数)
        :return: 打印出输入的字符串
        '''
        print(words)

my_module = My_module("Robin", "male") # 创建My_module()类的一个对象

print(f"In {my_module.country}") # 引用类属性
print(f"This is {my_module.name}.") # 引用对象属性
my_module.say_hi("Nice to meet you sir!") # 调用方法


In China
This is Robin.
Nice to meet you sir!

1.2 核心

函数是Python中的第一类对象 ,可以把函数赋值给变量,对该变量进行调用,可实现原函数的功能。
(变量——函数——函数式编程)

变量的作用域

由于函数也是对象,这部分可以参考:Python:变量的作用域与LEGB原则

参数传递

这里主要介绍两个特殊的参数传递方法(包裹传参):*args**kwargs

首先注意一点*args**kwargs只是参数传递的形式,并不是说参数名一定要使用这里的argskwargs

  • *args
    传递可变长度的参数,在参数数目未知的情况下可以使用。

    def args_passing1(*args):
        print(args)
    
    
    args_passing1('what', 'should', 'I', 'do')
    
    def args_passing2(*args):
        for i in args:
            print(i)
    
    ('what', 'should', 'I', 'do')
    just
    do
    it
    
  • **kwargs
    传递的参数为键值对(key-value)的形式

    def kwargs_passing(**kwargs):
        for k, v in kwargs.items():
            print(f'{k} = {v}')
            print((k,v))
    
    kwargs_passing(key_name='robin')
    
    key_name = robin
    ('key_name', 'robin')
    

2. 高级玩法

2.0 写在前面

普通的函数已经不能再满足人们的欲望,所以根据需求,又诞生了很多相对来说较为高级的玩法。

简单理解

  • 懒得定义函数名:匿名函数——便于作为参数传递出去
  • 在函数里面定义和调用另一个函数:嵌套函数——便于封装(隐藏数据)
  • 将一个函数作为参数:高阶函数——接受别的函数作为参数
  • 在函数内部递归调用函数自身:递归函数
  • 闭包函数
  • 装饰器函数

本质框架

上面一下列举了这么多的函数,却没有讲清楚他们之间的联系,而这才是重点!

  • 函数为一等对象
    • 高阶函数
  • 函数作用域
    • 嵌套函数
      • 闭包函数.:①代码复用②减少函数参数->减少函数参数
        • 装饰器

注:
闭包函数:函数+自由变量
装饰器:函数+函数型自由变量

2.1 匿名函数 lambda

首先,匿名函数是一个函数表达式
其次, 匿名函数很好地体现了函数式编程的特征(同map、filter、reduce等其它高阶函数一样)

匿名函数语法:lambda argument_list: expression
lambda 参数: 表达式

注意:这里的表达式(expression)实质上就是匿名函数的返回值,因此只能是表达式,而不能是语句

# 以下两种相等同
# 1.不使用匿名函数
def f(x):
	return x * x
	
# 2.使用匿名函数
lambda x: x * x

与普通函数一样,匿名函数除了普通调用,也可以作为其他函数的输入参数。

f = lambda x: x * x
print(f(2)) # 4
# 匿名函数f作为map()函数的第一个参数
f = lambda x: x * x
print(list(map(f, [1, 2]))) # [1, 4]
#  lambda 与 sort()搭配
d = ["ale","apple","monkey","plea"]
d.sort(key = lambda x : [-len(x), x])
print(d)

['monkey', 'apple', 'plea', 'ale']

[-len(x), x]完成了两个操作:
一是将长的字符串放在前面(本身是升序,但是加了负号,就将最大的长度变为了最小的负数),第二是将字符串按照字母排序。

2.2 嵌套函数

定义:在函数内部定义一个函数

# 函数中套着另一个函数

def f1():
    print("outer func")
    def f2():
        print('inner func')
    f2()
f1()
outer func
inner func

添加链接描述

2.3 高阶函数

满足下述条件之一的函数称之为高阶函数(Higher-order Functions)
(1)接收函数作为参数
(2)或者返回一个函数

添加链接描述

# ①函数作为参数
def f1():
    print('Hi')

def f2():
    f1()
    print('This is Robin')

f2()
Hi
This is Robin

结果:

# ②函数作为返回值
def f1():
    print('Hi')

    def f2():
        print('This is Robin')
    return f2()
f1()

结果:

Hi
This is Robin

常见高阶函数:map,reduce、filter

  • map

map(function, iterable) -> iterator

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

  • reduce

reduce(function, iterable) —> value

reduce把一个函数作用在一个可迭代对象,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算

  • filter

filter(function, iterable) —> iterator

filter 将可迭代对象中的每一个元素,传递给函数进行判断,最后返回结果为True的元素组成的一个iterator

  • sorted

sorted(iterable, key, reverse)—> list

sorted 函数默认将序列升序排列后返回一个新的 list,还可以自定义键函数(key)来进行排序,也可以设置reverse参数确定是升序还是降序

关于更为强大map,reduce、filter ,这里还有一份较为详细的总结Python 高阶函数:一文搞透 map()、reduce()、filter()

2.4 递归函数

递归概念:所谓递归函数,就是在内部调用自己的函数

递归的关键有三点:

  • 明确函数要解决的问题
  • 寻找递归结束条件
  • 找出等价表达式

例子:这里简单的给出求0-100之和的两个例子

# 计算0到100的和

# ①
# def sum(n):
#     if n == 0:
#         return 0
#     else:
#         return sum(n-1) + n
#
# r = sum(100)
# print(r)

# ②
# def sum(n):
#     if n < 2: # or n <= 1
#         return n
#     else:
#         return sum(n-1) + n
#
# r = sum(100)
# print(r)

这两个例子尽管递归结束条件选取的不同,但是都是正确的,结果都为5050

更多详细的内容在这里有总结:Python 递归

2.5 闭包函数

闭包概念

刚开始学习闭包是,网上看到了以下定义:

理解闭包:

  • 延伸了作用域的函数
  • 如果一个函数定义在另一个函数的作用域内,并且引用了外层函数的变量,则该函数称为闭包
  • 闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)

后来才发现,它掉了非常重要的一点:还需要return内部函数,正确的闭包定义应该如下:

function1里嵌套function2,内部的function2可以访问外部function1里的变量,且外部function1 return 的是内部function2时,外部函数就是一个闭包,

def function1(x):
    def function2(y):
        return x + y
    return function2

即:
闭包必须包含三个元素
①嵌套函数
②环境/自由变量
③return 内部函数

具体点说闭包的三个特征就是:

1.闭包函数必须有内嵌函数

2.内嵌函数需要引用该嵌套函数上一级namespace中的变量

3.闭包函数必须返回内嵌函数

举例:

def fun_out(a):
    def fun_in(b):
        return a + b
    return fun_in
    
fun1 = fun_out(1)

其中fun1函数是一个闭包,它携带着fun_out中定义的a变量,值为1。

why 闭包

(1)闭包 VS 类
还是上面得到例子,再定义一个函数fun5。

def fun_out(a):
    def fun_in(b):
        return a + b
    return fun_in
    
fun1 = fun_out(1)

fun5 = fun_out(5)
fun1(5) # 6
fun1(10) # 11

fun5(5) # 10
fun5(10) # 15

我们可以发现fun1和fun5两个函数的定义相同,只是携带的自由变量不同,便成为了两个函数
由此闭包可以作为函数工厂,生产出功能类似,但是会有细微差别的函数。

所以,我们也可说,闭包就是引用了自由变量的函数。

观察上面的例子,很容易发现跟Python的使用很接近!但是这比用类来实现更优雅

总的来说,闭包使得函数式编程拥有了类似面向对象编程的一种手法。

(2)闭包(局部变量) VS 全局变量

闭包作用

  • 想要改进如下代码:
def line1(x):
    return x + 1

def line2(x):
    return 2*x + 1

def line3(x):
    return 5*x + 10

def line4(x):
    return -2*x - 6
  • 可能的思路
def line(x, a, b):
    return a*x + b

line1 = line(x, 1, 1) 
line2 = line(1, 1, 1) 

但是这样就出问题了,因为需要知道全部的参数值

  • 使用闭包
def line_conf(a, b): # 使用外部函数的参数a和b说明直线的参量,这样可以复用内同一个闭包
    def line(x):
        return a*x + b
    return line # 再将返回值设为(内部)函数体

line1 = line_conf(1, 1)  # 记住闭包本质也是函数
line2 = line_conf(2, 1)

可以看出闭包作用

  • ① 提高代码复用性
  • ② 减少函数的参数:line()函数有三个参数(自变量x以及a和b),通过line_conf()这个闭包,我们可以预设a和b的值,从而起减参的效果

换一种思路:理解本质

之前是由表及里,从概念、实例和作用等方面讲了闭包,现在我们换一种思路:从接近本质的地方出发,去思考。

2.6 装饰器函数

概念

装饰器是闭包的一个应用,只是携带的自由变量是一个函数

待看,参考:python闭包

换一种思路

待看!
装饰器

参考:

  1. Python基础总结(1)
  2. Python进阶:函数式编程(高阶函数,map,reduce,filter,sorted,返回函数,匿名函数,偏函数)…啊啊啊——比较好的总结!
  3. python闭包——讲闭包及系列知识很不错
  4. 装饰器——别开生面,讲的浅显易懂,接近本质
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值