Python基础-----列表生成式、偏函数、高阶函数、闭包、装饰器

列表生成式

列表生成式(列表推导式):通俗理解使用for循环快速创建一个列表,最终要获取一个列表

下面这个我们经常使用比较麻烦的方法:

my_list=[]
for i in range(1,6):
    print(i)
    my_list.append(i)
print(my_list)

输出:[1, 2, 3, 4, 5]

这个是列表生成式:

my_list=[value for value in range(1,6)]
print(my_list)

输出:[1, 2, 3, 4, 5]

列表生成式还能对数值进行计算:

my_list=[value*2 for value in range(1,6)]
print(my_list)

输出:[2, 4, 6, 8, 10]

循环里in后面只要是容器,都可以使用,如果是字典就会默认循环key

result =[value for value in {1:'abc',2:'ab'}.values()]
print(result)

输出:['abc', 'ab']

给输出添加内容:

result =[value+'%' for value in ['15','66']]
print(result)

输出:['15%', '66%']

可以同时内嵌多个循环:

my_list=[(x,y) for x in range(1,3) for y in range(1,3)]
print(my_list)

输出:[(1, 1), (1, 2), (2, 1), (2, 2)]

取偶数:

my_list=[value for value in range(1,11) if value%2 == 0]
print(my_list)

输出:[2, 4, 6, 8, 10]

引用

程序中的数据在内存中的地址, 即内存地址

a存储的是10在内存中的一个地址,b存储的是a保持的内存地址,现在a和b存储的内存地址是同一个,以后可以通过内存地址获取对应数据。
”id(变量名)" 获取的内存地址收拾一个十进制的数据,hex()是16进制

a = 10
b = a
print('a的内存地址:',id(a))
print('b的内存地址:',id(b))
print('a的内存地址:',hex(id(a)))
print('b的内存地址:',hex(id(b)))
print(a,b)

输出:
a的内存地址: 1768343824
b的内存地址: 1768343824
a的内存地址: 0x6966c910
b的内存地址: 0x6966c910
10 10

可变类型与不可变类型

可变类型: 可以在原有数据的基础上对数据进行修改(添加or删除or修改),修改后内存地址不变 【列表,集合,字典】
不可变类型: 不能在原有数据基础上进行修改,如果修改就赋予新值,内存地址改变【字符串,数字,元组】

可变类型:我们使用列表写了一些数据,然后对其进行修改、添加、删除,最后的内存地址都没有发生变化,这就是可变类型。字典和集合可以自己自行调试一下

my_list = [1,5,6]
print(id(my_list))
my_list[0]=2
my_list.append(7)
del  my_list[1]
print(id(my_list))

输出:
2835920
2835920

不可变类型:使用string来尝试一下,第三句会报错,因为是不允许改变string类型数据的,然后我们给变量重新又赋值了“world”,可以看到输出的内存地址发生了变化,证明我们已经重新赋值了。数组和元组也一样

my_str = 'hello'
print(my_str,id(my_str))
my_str[0]='a'    #这个操作会报错的,说不能在原有数据上改变
print(id(my_str))
my_str='world'   #内存地址发生改变
print(id(my_str))

输出:
64911968
64912032

global的使用

定义不可变类型的全局变量,声明要修改全局变量, 这种修改会导致全局变量的内存地址发生变化。加了global后就是给g_num重新赋值,内存地址改变了

g_num = 10
print("函数外:",id(g_num))
def modify():
    global g_num
    g_num=1
    print("修改后:",g_num)
    print("函数内:", id(g_num))
modify()
print(g_num)

输出:
函数外: 1769457936
修改后: 1
函数内: 1769457792
1

定义可变类型的全局变量:在原有数据上加数据,如果只是修改数据,可以不需要加global。不加global时内存地址是没有改变的,加上后,即改变外部g_list的内存地址,值也会变化。这里要注意:如果不写global g_list,仅仅只写g_list=[1,2],这个只是创建一个局部变量,和外部的g_list没有任何关系,而加上global后就是改变外部的g_list,意义就是希望创建一个新的内存块存储这个修改后的值,并且外部的变量的值也被修改了

g_list = [1,5,10]
print('函数外:',id(g_list))

def modify():
	下面这句只是给外部这个变量添加一个元素,并没有改变内存地址哦!
	#g_list.append(4)
	
    global g_list
    g_list=[1,2]
    print("修改后:",g_list)
    print("函数内:",id(g_list))
modify()
print(g_list)

输出:
函数外: 17974736
修改后: [1, 2]
函数内: 17975896
[1, 2]

公共运算符的操作

  • “+”符号可以完成list,tuple,str拼接
my_str1 = 'hello'
my_str2 = 'world'
result = my_str1+my_str2
print(result)

my_list1=[1,2]
my_list2=[3,4]
result=my_list1+my_list2
print(result)

my_tuple1=(1,4)
my_tuple2=(5,3)
result=my_tuple1+my_tuple2
print(result)

输出:
helloworld
[1, 2, 3, 4]
(1, 4, 5, 3)
  • “*”星符号 可以完成list,tuple,str的复制
result  ='-'*20
print(result)
result='*'*2
print(result)

my_list=[1,2]
result=my_list*2
print(result)

my_tuple=(4,5)
result=my_tuple*3
print(result)

输出:
--------------------
**
[1, 2, 1, 2]
(4, 5, 4, 5, 4, 5)

列表、元组、集合的类型转换

集合是无序的

  • 列表转集合、元组
my_list=[1,2,2,3]
result = set(my_list)
print(result,type(result))
result = tuple(my_list)
print(result,type(result))

输出:
{1, 2, 3} <class 'set'>
(1, 2, 2, 3) <class 'tuple'>
  • 元组转集合、列表
my_tuple=(4,5)
result = set(my_tuple)
print(result,type(result))
result = list(my_tuple)
print(result,type(result))
输出:
{4, 5} <class 'set'>
[4, 5] <class 'list'>
  • 集合转列表、元组
my_set={6,7}
result =  tuple(my_set)
print(result,type(result))
result = list(my_set)
print(result,type(result))

输出:
(6, 7) <class 'tuple'>
[6, 7] <class 'list'>

函数文档说明

这个功能是为了让别人看不懂自己写的代码的时候,可以通过help()函数可以获取这个自定义函数的信息,只需要把代码写完之后,写上3个单引号,再回车,就会出现函数的注释,添加文字说明就可以了!
help函数用于三方公司查看自己公司接口方法或者函数的时候使用

# 计算数字和的函数
def sum_num(num1,num2):
    '''
    计算数字和的函数
    :param num1: 第一个数字
    :param num2: 第二个数字
    :return: 返回值
    '''
    result = num1+num2
    return  result
value = sum_num(1,2)
print(value)
help(sum_num) 

偏函数(用的不多)

指明函数的参数偏爱某个值,就是偏函数
当我们写函数的时候,有些值不写,例如n3,然后我们给它一个默认值,函数就会直接使用默认值。但是有时候我们又不想默认值一直是同一个,例如show2,希望是2。如果想改变其默认值,又得写一个函数,太麻烦了。所以可以使用一个python提供的功能

def show(n1,n2,n3=1):
    result = n1+n2+n3
    return result
result = show(1,2)
print(result)

def show2(n1,n2,n3=2):
    result= show(n1,n2,n3=2)
    return result
result = show2(1,2)
print(result)
输出:
4
5

系统提供了一个模块可以方便使用偏函数, functools。它可以指明函数的参数设置为某个值
functools会返回一个函数(这里是new_func),就是偏函数。我们对show2进行n2的设置,现在n2=2,n3=2,输入1,输出就为5了

import functools
new_func=functools.partial(show2,n2=2)  #返回的函数就是偏函数
result=new_func(1)
print(result)

输出:
5

可能大家觉得这个好像没啥用,其实我们还能对系统内置函数进行偏函数设置哦!
我们把int函数改成输入二进制数值,输出是转换为十进制

result=int('123')
new_func = functools.partial(int,base=2)  #改二进制
result=new_func('11')
print(result)

输出:
3

返回函数

在函数里面返回一个函数
注意:返回值不要加(),加了就是等于执行函数

def show():
    def inner():
        print('hhh')

    return inner  # 加了()的意思是执行

newfunc = show()  # 获取返回的函数
newfunc()  # 执行返回的函数

输出:hhh

那这个返回函数多数是怎么用呢?可以看看下面这个计算器例子:

def calc(operation):
    if operation == '+':
        def sum_n(num1, num2):
            result = num1 + num2
            return result

        return sum_n
    elif operation == '-':
        def jq_n(num1, num2):
            result = num1 - num2
            return result

        return jq_n
        
new_func = calc('+')
result = new_func(1, 2)
print(result)

输出:3

高阶函数

上面那个返回函数也可以算作高阶函数的一种。
高阶函数的定义:当一个函数的参数可以接受/返回另外一个函数,那么这个函数就叫做高阶函数。
高阶函数针对的是接受的是函数或者返回的是函数,那么类似于这样的函数统称高阶函数

  • 这里cal_num接受了一个函数
def sum_num(num1, num2):
    result = num1 + num2
    return result

# 这是高级函数,因为接受的参数是一个函数
def calc_num(num1, num2, new_func):
    value = new_func(num1, num2)
    return value


result = calc_num(1, 2, sum_num)
print(result)
输出: 3
  • 接受了一个函数,还可以返回一个函数
def test(newFunc):
    newFunc()
    def inner():
        print("this is an inner function")
    return inner
def show_msg():
    print("show 一下")

new_func = test(show_msg)
new_func()

输出:
show 一下
this is an inner function

闭包(有时候会考的点)

在函数嵌套的情况下,内部函数使用了外部函数的参数或者变量,并把这个内部函数返回,那么返回的函数可以称为闭包(对应的就是一个函数)
闭包也是高阶函数,下面是闭包实现的条件:

  1. 函数嵌套
  2. 内部函数使用了外部函数的变量
  3. 外部函数返回的函数就是闭包
def show(msg):
    num = 10
    def inner():
        print(num,msg)
    return inner
new_func = show("hhh")
print(new_func)
new_func()

输出:
<function show.<locals>.inner at 0x02F5E468>
10hhh
  • 闭包应用场景,可以根据参数生成不同的返回函数。闭包的好处是可以根据条件生成不同的函数
def hello(msg, count):
    def return_msg():
        result = msg * count
        return result

    return return_msg

new_func1 = hello('A', 2)
print(new_func1)
result = new_func1()
print(result)
new_func2 = hello('B',2)
print(new_func2)
result = new_func2()
print(result)

输出:
<function hello.<locals>.return_msg at 0x02FDE468>
AA
<function hello.<locals>.return_msg at 0x02FDE4B0>
BB

装饰器(重点)

装饰器:本质上就是一个函数,可以给原函数的功能上进行扩展,这样的好处是,不改变原函数的定义以及调用的操作。(有点类似于继承的感觉)

在打印A的前面,再打印一波B,但是不改变函数,如何操作?
装饰器—>通过闭包完成装饰器。
下面被注释的一行代码,代表把原函数放入decorator函数,然后内部函数inner是先打印B,然后再执行show函数,返回了inner函数。这样子就等于在执行show函数前先打印一波B了。
但是这样写不够简便,所以在原函数上面加个@decorator,就等于省去了那一行代码!
提示:在使用@decorator的时候,装饰器的代码就会执行

def decorator(new_func):
    #返回函数是闭包
    def inner():
        print('B' * 10)
        new_func()
    #返回的函数是闭包
    return inner

#原函数
@decorator
def show():
    print('AAAAAAAA')
#show = decorator(show)  #用被改的函数的名字
show()

输出:
BBBBBBBBBB
AAAAAAAA
装饰器要装饰一个带有参数的函数

这个装饰器可以装饰有参数有返回值的,也可以装饰有参数无返回值的函数。
因为有参数,所以传入到内部函数需要参数,返回的函数也要有参数
只要记住:result = sum_num(1,2)已经是替换成了执行inner函数

def decorator(new_func):   
    def inner(num1,num2):  #加上参数
        print("计算结果为:")
        return new_func(num1,num2) '因为要返回值,所以要return'
    return inner

@decorator #sum_num = decorator(sum_num)
def sum_num(num1,num2):  '装饰有参数有返回值'
    result = num1+num2
    return result
result = sum_num(1,2)  '其实这句就是执行inner函数!!!'
print(result)

@decorator  #sum_msg= decorator(sum_msg)
def sum_msg(num1,num2):  '装饰有参数无返回值'
    print(num1,num2)
result = sum_msg(1,4)   '因为这个函数没有返回值,所以输出为None'
print(result)

输出:
计算结果为:
3
计算结果为:
1 4
None
通用的装饰器

刚刚上面两个原函数,刚刚好参数数目相同,但是如果我们遇到要用一个装饰器修饰含有不同参数个数的原函数,要怎么做呢?这个时候要用不定长参数

  • 拆包:args它是一个元组,它把传入的数据放进了args元组中,而kwargs是一个字典。把可迭代对象进行拆分(包括字典、元组、列表、字符串、集合)。一种是以变量的方式来接收,另一种是用‘*’号
    q = (1,2,3)
    a,b,c = q
    print(*q)
def decorator(new_func):
    def inner(*args,**kwargs):
        print("计算结果为:")
        return new_func(*args,**kwargs)  #这里需要对不定长参数进行拆包
    return inner

@decorator
def sum_num(num1,num2):
    result = num1+num2
    return result
result = sum_num(1,2)
print(result)

@decorator
def sum_msg(num1,num2):
    print(num1,num2)
result = sum_msg(1,4)
print(result)

@decorator
def show():
    print("我是一个无参数无返回值的函数")
show()

输出:
计算结果为:
3
计算结果为:
1 4
None
计算结果为:
我是一个无参数无返回值的函数
带有参数的装饰器

打印一波1的前面,打印一波A,B,C…你总是想改变这个字母,那该怎么操作?
我们不止创建了装饰器,还返回了装饰器,装饰器再返回函数inner,就有种嵌套的感觉而已
把@后面的操作相当于执行了一个函数,返回一个装饰器

def get_decorator(char):
	#定义装饰器	
    def decorator(func):
        def inner():
            print(char * 10)
            func()

        return inner
    return decorator
#把@后面的操作相当于执行了一个函数,返回一个装饰器
@get_decorator('A')  #有参数的装饰器
def show():
    print("11111")
show()

其实是没啥区别的,反正你使用了装饰器,其实就已经不是原函数了,你跑去找装饰器就好,然后装饰器需要调用回原函数的时候,我们再看原函数就好了~

原函数使用多个装饰器

@decorator1 show => decorator1(decorator2.inner) =>decorator1.inner
@decorator2 => show = decorator2(show) => decorator2.inner
这里有一层有点复杂的关系,首先我们要直到装饰器1会把装饰器2和函数看成一个整体,所以从最里面的一层开始看,decorator2的inner的func是show,而decorator1的inner的func是decorator2.inner。最先执行的是外层的装饰器,这个实现类似于嵌套

def decorator1(func):
    def inner(): #inner其实就是你封装函数的代码
        print('-'*30)
        func()
    return inner

def decorator2(func):
    def inner(): #inner其实就是你封装函数的代码
        print('*'*30)
        func()
    return inner

@decorator1 # show => decorator(decorator2.inner) =>decorator1.inner
@decorator2 # => show = decorator2(show) => decorator2.inner
def show():
    print("AAAAA")
show()

输出:
------------------------------
******************************
AAAAA
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值