函数和lambda笔记

#!/usr/bin/python3
# 函数的文档
def doc_demo(x,y):
    '''
    输入x,y
    获取x、y中的较大值
    '''
    z = x if x>y else y
    return z
# help(doc_demo)
print(doc_demo.__doc__)
# print(help(doc_demo)) # pycharm执行会报错,命令行执行正常
# 多个返回值,自动封装为元组
def sum_and_avg(list):
    sum = 0
    count = 0
    for e in list:
        # 如果元素e是数值
        if isinstance(e, int) or isinstance(e, float): # isinstance()函数 判断是不是指定类型的实例
            count += 1
            sum += e
    return sum, sum / count
my_list = [20, 15, 2.8, 'a', 35, 5.9, -1.8]
# 获取sum_and_avg函数返回的多个值,多个返回值被封装成元组
tp = sum_and_avg(my_list) #①
print(tp)
# 使用序列解包来获取多个返回值
s, avg = sum_and_avg(my_list) #②
print(s)
print(avg)

# 递归函数:函数内部不断调用自身,必须保证有约束条件(某个时刻返回值是确定的),不然会无穷递归类似于死循环
def fn(n):
    if n==0:
        return 1
    elif n==1:
        return 4
    else:
        return 2*fn(n-1)+fn(n-2)
print(fn(10))
# 形参:形式参数,在函数的定义处定义的参数
# 实参:实际参数,在函数调用处定义的参数
# 关键字(keyword)参数
def girth(key,word):
    return (key,word)

print(girth(1,2))
print(girth(key=1,word=2))
# print(girth(1,word=2)) # 混合使用关键字参数和位置参数,位置参数必须要在关键字参数之前

# Python要求将默认值参数定义在形参的最后
def say_hi(name,message='456'):
    return (name,message)

def test(x,y,z=3,*name,**value): # 最多支持一个可变参数*和**可变关键字参数,此时可变参数会作为元组输入,可变关键字参数作为词典传入
    print('name',name)
    print('z',z)
    for i in name:
        print('i的值是%s'%(i))
    print('value',value)

test(1,2,3,'123',4,'567',value1=1,value2=2)
test(1,2,value1=1,value2=2) # 若想默认值参数z生效,则只能将前面的位置参数传入,后面使用关键字参数

# 可变个数参数:本质是多个参数作为元组传入;位置可前可后,一个函数只能带一个普通的参数收集的形参
def autoDemo(a,*b):
    print(a)
    print()
    for i in b:
        print(i,end=",")
autoDemo(1,2,3,4,5,6,7)

# 逆向参数收集:将sequence中的元素拆开传入函数,列表和元组为*;字典**,会以关键字参数的方式传入
def reversal(name,*values):
    print('name的参数',name)
    print('valuses的参数',values)
listdemo=['name1',1,2,3]
reversal(*listdemo)

a,b=6,7
a,b=b,a #右边会封包,然后传给左边
print(a,b)

'''
函数的参数传递机制
python函数的参数传递方式为值传递:将实际参数的副本传入函数,而参数本身不受影响

指针变量(引用变量)
1、程序开始创建了一个字典对象,并定义了一个dw引用变量指向字典对象,这意味着此时内存中有两个东西:对象本身和指向该对象的引用变量。
2、主程序中的 dw 是一个引用变量(也就是一个指针),它保存了字典对象的地址值,当把 dw 的值赋给swap()函数的dw参数后,就是让swap()的dw参数也保存这个地址值,即也会引用到同一个字典对象。


1、不管什么类型的参数(实参),在Python函数中对参数直接使用"="符号赋值是没用的 ,直接使用“=”符号赋值并不能改变参数(实参)。
2、如果需要让函数修改某些数据,则可以通过把这些数据包装成列表、字典等可变对象,然后把列表、字典等可变对象作为参数传入函数,在函数中通过列表、字典的方法修改它们,这样才能改变这些数据。
'''
# 变量值参数输入不会改变
def swap(a , b) :
    # 下面代码实现a、b变量的值交换
    a, b = b, a
    print("swap函数里,a的值是", \
        a, ";b的值是", b)
a = 6
b = 9
swap(a , b)
print("交换结束后,变量a的值是", \
    a , ";变量b的值是", b)
# 指向性参数传入可改变
def swap(dw):
    # 下面代码实现dw的a、b两个元素的值交换
    dw['a'], dw['b'] = dw['b'], dw['a']
    print("swap函数里,a元素的值是",\
        dw['a'], ";b元素的值是", dw['b'])
    # 把dw直接赋值为None,让它不再指向任何对象
    dw = None
dw = {'a': 6, 'b': 9}
swap(dw)
print("交换结束后,a元素的值是",\
    dw['a'], ";b元素的值是", dw['b'])

# 变量的作用域:变量的作用范围被称为它的作用域
# 局部变量:在函数内部作用
# 全局变量:全局都可作用
# globals():该函数返回全局范围内所有变量组成的“变量字典”
# locals():该函数返回当前局部范围内所有变量组成的“变量字典”
# vars(object):获取在指定对象范围内所有变量组成的“变量字典”。如果不传入object参数,vars()和 locals()的作用完全相同。
# 通过locals()或者globals()获取的全局变量可以被修改,并影响到变量本身;通过locals()获取的局部变量即使修改也不会影响到局部变量
def test():
    age = 20
    # 直接访问age局部变量
    print(age) # 输出20
    # 访问函数局部范围的“变量数组”
    print(locals()) # {'age': 20}
    # 通过函数局部范围的“变量数组”访问age变量
    print(locals()['age']) # 20
    # 通过locals函数局部范围的“变量数组”改变age变量的值
    locals()['age'] = 12
     # 再次访问age变量的值
    print('xxx', age) # 依然输出20
    # 通过globals函数修改x全局变量
    globals()['x'] = 19
x = 5
y = 20
print(globals()) # {..., 'x': 5, 'y': 20}
# 在全局访问内使用locals函数,访问的是全局变量的“变量数组”
print(locals()) # {..., 'x': 5, 'y': 20}
print(globals())
# 直接访问x全局变量
print(x) # 5
# 通过全局变量的“变量数组”访问x全局变量
print(globals()['x']) # 5
# 通过全局变量的“变量数组”对x全局变量赋值
globals()['x'] = 39
print(x) # 输出39
# 在全局范围内使用locals函数对x全局变量赋值
locals()['x'] = 99
print(x) # 输出99
print(test())
print(x) # x可以被函数内的globals函数修改

# Python语法规定:在函数内部对不存在的变量赋值时,默认就是重新定义新的局部变量。因此这行代码相当于重新定义了name局部变量,\
# 这样name全局变量就被遮蔽(不在函数内部作用)了,所谓的局部变量遮蔽全局变量,所以下面这段会报错。
# name='123'
# def a123():
#     print(name) # 会报错,因为下一行赋值导致全局变量name被局部变量遮蔽,从而报未定义前的引用
#     name = 'afv'
# a123()
# print(name)

# 函数中访问遮蔽变量的两种方式
# 1、通过global()函数访问
name='123'
def accessHide1():
    print(globals()['name'])
    name='456'
accessHide1()

# 2、通过global在函数中定义全局变量:global name声明以后
# 程序会把 name变量当成全局变量,这意味着accessHide2()函数后面对name赋值的语句只是对全局变量赋值,而不是重新定义局部变量
name='charters'
def accessHide2():
    global name
    print(name)
    name='landel'
accessHide2()

# 局部函数:局部函数对外部是隐藏的,只能在其封闭(enclosing)函数内有效
def get_mathCalc(module,n1):
    def square(n):
        return n*n
    def cube(n):
        return n*n*n
    def factorial(n):
        result=1
        for i in range(2,n+1):
            result *= i
    # 在函数内调用局部函数
    if module == 'square':
        return square(n1)
    elif module == 'cube':
        return cube(n1)
    elif module == factorial:
        return factorial(n1)
print(get_mathCalc('square',2))
# 局部函数变量遮蔽
def hideLocal1():
    name='charters'
    def local1():
        # print(name) # 受后面影响,会定义name为局部变量,函数中的name变量被遮蔽导致报错
        name=123
# 在局部函数中访问遮蔽变量的方式
def hideLocal2():
    name='charters'
    def local2():
        nonlocal name # 这里nonlocal和global的作用相似,看字面意思
        print(name)
    local2()
hideLocal2()

# 函数作为变量使用
# 函数也是一种值:所有函数都是function对象,把函数赋值给变量,可以通过变量来调用它
def pow(base, exponent) :
    result = 1
    for i in range(1, exponent + 1) :
        result *= base
    return result
# 将pow函数赋值给my_fun,则my_fun可当成pow使用
my_fun = pow
print(my_fun(3 , 4)) # 输出81
# 定义一个计算面积的函数
def area(width, height) :
    return width * height
# 将area函数赋值给my_fun,则my_fun可当成area使用
my_fun = area
print(my_fun(3,4)) # 输出12

# 函数可以作为形参传入函数:可以动态改变程序代码-实现在函数内部动态调用不同函数
# 定义函数类型的形参,其中fn是一个函数
def map(data, fn) :
    result = []
    # 遍历data列表中每个元素,并用fn函数对每个元素进行计算
    # 然后将计算结果作为新数组的元素
    for e in data :
        result.append(fn(e))
    return result
# 定义一个计算平方的函数
def square(n) :
    return n * n
# 定义一个计算立方的函数
def cube(n) :
    return n * n * n
# 定义一个计算阶乘的函数
def factorial(n) :
    result = 1
    for index in range(2, n + 1) :
        result *= index
    return result
data = [3 , 4 , 9 , 5, 8]
print("原数据: ", data)
# 下面程序代码3次调用map()函数,每次调用时传入不同的函数
print("计算数组元素的平方")
print(map(data , square))
print("计算数组元素的立方")
print(map(data , cube))
print("计算数组元素的阶乘")
print(map(data , factorial))
# 获取map的类型
print(type(map))

# 函数作为返回值:动态接受不同的局部函数
def get_math_func(funciton):
    def square(n):
        return n*n
    def cube(n):
        return n*n*n
    def factorial(n):
        result=1
        for i in range(2,n+1):
            result *= i
        return result
    # 返回子局部函数
    if funciton == 'square':
        return square
    elif funciton == 'cube':
        return cube
    elif funciton == 'factorial':
        return factorial
# 调用函数,接受局部函数
math1=get_math_func('square')
print(math1(2))
math2=get_math_func('cube')
print(math2(3))
math3=get_math_func('factorial')
print(math3(3))

# 使用lambda表达式代替局部函数:1、局部函数名没有意义,2、单行表达式
# 格式:lambda [parameter_list] : 表达式
# lambda 表达式依然有如下两个用途
# 对于单行函数,使用lambda表达式可以省去定义函数的过程,让代码更加简洁。
# 对于不需要多次复用的函数,使用lambda表达式可以在用完之后立即释放,提高了性能
def get_math_func1(function):
    if function=='square':
        return lambda n:n*n
    elif function=='cube':
        return lambda n:n*n*n
    elif function=='factorial':
        return lambda n:n*(n+1)/2
math1=get_math_func1('square')
print(math1(2))
math2=get_math_func1('cube')
print(math2(3))
math3=get_math_func1('factorial')
print(math3(5))
# 通过lambda表达式来调用Python置的map()函数
x=map(lambda n:n*n,range(8))
print(x) #object
print([e for e in x ])
y=map(lambda n:n*n if n%2==0 else 0,range(8))
print([e for e in y])

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值