列表生成式
列表生成式(列表推导式):通俗理解使用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
闭包(有时候会考的点)
在函数嵌套的情况下,内部函数使用了外部函数的参数或者变量,并把这个内部函数返回,那么返回的函数可以称为闭包(对应的就是一个函数)
闭包也是高阶函数,下面是闭包实现的条件:
- 函数嵌套
- 内部函数使用了外部函数的变量
- 外部函数返回的函数就是闭包
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