各种类型函数讲解以及装饰器

@函数的定义

以下是简单的规则:
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。函数内容以冒号起始,并且缩进。return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
基本格式:

def 函数名(参数):
	函数体
	return 返回值

@函数的参数

  • 必需参数
    必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
    调用 printme() 函数,你必须传入一个参数,不然会出现语法错误:
  • 关键字参数
    关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。
    使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

以下实例在函数 printme() 调用时使用参数名:

#可写函数说明
def printme( str ):
   "打印任何传入的字符串"
   print (str)
   return
 
#调用printme函数
printme( str = "关键字参数")

以下实例中演示了函数参数的使用不需要使用指定顺序:

#可写函数说明
def printinfo( name, age ):
   "打印任何传入的字符串"
   print ("名字: ", name)
   print ("年龄: ", age)
   return
 
#调用printinfo函数
printinfo( age=50, name="runoob" )
  • 默认参数
    调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:
def printinfo( name, age = 35 ):
   "打印任何传入的字符串"
   print ("名字: ", name)
   print ("年龄: ", age)
   return
 
#调用printinfo函数
printinfo( age=50, name="runoob" )
print ("------------------------")
printinfo( name="runoob" )

运行结果:
名字:  runoob
年龄:  50
------------------------
名字:  runoob
年龄:  35
  • 不定长参数
    你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名。python自定义函数中有两种不定长参数,第一种是*args,在传入额外的参数时可以不用指明参数名,直接传入参数值即可。第二种是**kargs,这种类型返回的是字典,传入时需要指定参数名。
    加了一个星号 * 不定长参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。加了两个星号 ** 的参数会以字典的形式导入,存放已命名的变量参数。
    实例1:
#使用不定长参数传固定值,注意,b、c可省略,a不可省略
def fuzhi(a, *b, **c):
    print(a)
    print(b)
    print(c)
fuzhi(1,25,3,69,58,48,58)

运行结果:
1
(25, 3, 69, 58, 48, 58)
{
    
    }

实例2:

def fuzhi(a, *b, **c):
    print(a)
    print(b)
    print(c)
fuzhi(1,25,3,69,58,48,58,name='lly',age=18,she='yrr')

运行结果:
1
(25, 3, 69, 58, 48, 58)
{
    
    'name': 'lly', 'age': 18, 'she': 'yrr'}

@匿名函数

python 使用 lambda 来创建匿名函数。
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
lambda 只是一个表达式,函数体比 def 简单很多。
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

语法:
lambda [arg1 [,arg2,…argn]]:expression

实例1:

# 可写函数说明
sum = lambda arg1, arg2: arg1 + arg2
 
# 调用sum函数
print ("相加后的值为 : ", sum( 10, 20 ))
print ("相加后的值为 : ", sum( 20, 20 ))

运行:
相加后的值为 :  30
相加后的值为 :  40

实例2:

# 匿名函数:简化函数定义
# 格式: lambda 参数1,参数2,。。:运算

s = lambda a, b: a + b
print(s(4, 4))


def func(x, y, func):
    print(x, y)
    print(func)
    s = func(x, y)
    print(s)


# 调用func
func(1, 2, lambda x, y: x + y)
list2=[{
    
    'a':13,'b':56},{
    
    'a':40,'b':49},{
    
    'a':50,'b':1}]
m=max(list2,key=lambda x:x['b']+x['a'])
print(m)

运行结果:

8
1 2
<function <lambda> at 0x00000228306BBB70>
3
{
    
    'a': 40, 'b': 49}

实例2:

# map

list1 = [1, 2, 4, 7, 8, 9, 6, 3]
result = map(lambda x: x + 2, list1)
print(list(result))

func = lambda x: x if x % 2 == 0 else x + 1
result = func(5)
print(result)

result = map(lambda x: x if x % 2 == 0 else x + 1, list1)
print(list(result))

# reduce(): 对列表中的元素进行加减乘除运算
from functools import reduce

tuple1 = (3, 4, 5, 6, 7, 8)
result = reduce(lambda x, y: x + y, tuple1)
print(result)

tuple2 = (4,)
result = reduce(lambda x, y: x + y, tuple2, 10)
print(result)

# 动手测试减法
list2 = [12, 3, 5, 56, 4, 23, 14, 19, 10, 9]
result = filter(lambda x: x > 10, list2)
print(list(result))

运行结果:

[3, 4, 6, 9, 10, 11, 8, 5]
6
[2, 2, 4, 8, 8, 10, 6, 4]
33
14
[12, 56, 23, 14, 19]

@闭包

闭包是函数式编程的一个重要的语法结构,函数式编程是一种编程范式 (而面向过程编程和面向对象编程也都是编程范式)。在面向过程编程中,我们见到过函数(function);在面向对象编程中,我们见过对象(object)。函数和对象的根本目的是以某种逻辑方式组织代码,并提高代码的可重复使用性(reusability)。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
  不同编程语言实现闭包的方式是不同的,python中闭包从表现形式上看,如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
例如:

def func(a, b):
    c = 10

    def inner_func():
        s = a + b + c
        print('相加后的结果是', s)

    return inner_func


# 调用func
ifunc = func(6, 9)
ifunc1 = func(2, 8)

print(ifunc)
print(ifunc1)

ifunc()
ifunc1()

运行结果:
<function func.<locals>.inner_func at 0x000001A7FE08B840>
<function func.<locals>.inner_func at 0x000001A7FE08BBF8>
相加后的结果是 25
相加后的结果是 20

@装饰器

装饰器实际上就是为了给某程序增添功能,但该程序已经上线或已经被使用,那么就不能大批量的修改源代码,这样是不科学的也是不现实的,因为就产生了装饰器。
实例1:

import time


def decorate(func):
    print('------------第一层--------------')
    def wrapper(*args, **kwargs):
        print('正在校验中---------------')
        time.sleep(2)
        print('校验完毕------------------')
        func(*args, **kwargs)
    print('###########下一步就是return了###############')

    return wrapper


@decorate
def f1(n):
    print('---------------f1----------------', n)


@decorate
def f2(name, age):
    print('---------------f2----------------', name, age)
运行结果:
------------第一层--------------
###########下一步就是return了###############
------------第一层--------------
###########下一步就是return了###############

实例2:

import time

def decorate(func):
    print('------------第一层--------------')
    def wrapper(*args, **kwargs):
        print('正在校验中---------------')
        time.sleep(2)
        print('校验完毕------------------')
        func(*args, **kwargs)
    print('###########下一步就是return了###############')

    return wrapper

@decorate
def f1(n):
    print('---------------f1----------------', n)

@decorate
def f2(name, age):
    print('---------------f2----------------', name, age)

f1(4)
print(f1)
f2('lly', 18)
print(f2)

@decorate
def f3(student, clazz='1905'):
    print('{}的学生如下: '.format(clazz))
    for stu in student:
        print(stu)

students = ['lly', 'llg', 'ffrf', 'yrr']

f3(students)
print(f3)
运行结果:
------------第一层--------------
###########下一步就是return了###############
------------第一层--------------
###########下一步就是return了###############
正在校验中---------------
校验完毕------------------
---------------f1---------------- 4
<function decorate.<locals>.wrapper at 0x000001C8F77ABAE8>
正在校验中---------------
校验完毕------------------
---------------f2---------------- lly 18
<function decorate.<locals>.wrapper at 0x000001C8F77ABD08>
------------第一层--------------
###########下一步就是return了###############
正在校验中---------------
校验完毕------------------
1905的学生如下: 
lly
llg
ffrf
yrr
<function decorate.<locals>.wrapper at 0x000001C8F77ABE18>

注意:当有两个装饰器时,函数优先加载最近的装饰器。

猜你喜欢

转载自blog.csdn.net/LLY_A_/article/details/106962981