Python学习
函数
- 变长参数 *a, 以元组传入
参数用 *a ,输入的参数会以元组形式传入
def self_print(*a):
print(a)
print(type(a))
self_print(1,2,3,4,5,'a','c','s')
#(1, 2, 3, 4, 5, 'a', 'c', 's')
#
也可以普通参数和变长参数同时使用
参数按位置传递,最后的都放在变长参数里
但是变长参数一定要放在最后
def self_print(b,*a):
print(a)
print(type(a))
self_print(1,2,3,4,5,'a','c','s')
#(2, 3, 4, 5, 'a', 'c', 's')
#
变长参数不放在最后会报错
def self_print(*a,b):
print(a)
print(type(a))
self_print(1,2,3,4,5,'a','c','s')
#TypeError: self_print() missing 1 required keyword-only argument: 'b'
- 变长参数 **a, 以字典传入
参数用 **a ,输入的参数会以字典形式传入
def self_print(**a):
print(a)
print(type(a))
self_print(first_name='tf',last_name='xu')
#{'first_name': 'tf', 'last_name': 'xu'}
#
- 变长参数,混合使用
参数位置不能乱,必须形参顺序:位置参数,元组,字典
传入时参数也不能乱
def self_print(a,*b,**c):
print(a)
print(type(a))
print(b)
print(type(b))
print(c)
print(type(c))
self_print('ab',290,12,'a',first_name='tf',last_name='xu')
#ab
#
#(290, 12, 'a')
#
#{'first_name': 'tf', 'last_name': 'xu'}
#
如果有关键字参数或默认参数时:
有默认参数时,会因为自动的按顺序传,默认参数会用不到
应该不能另外传其他关键字参数,因为**本来就是传入关键字参数的字典
- 拆开输出的元组和列表 *a
a=(91,2,3,4,5)
print(*a)
#91 2 3 4 5
a=[91,2,3,4,5]
print(*a)
#91 2 3 4 5
a={'a':1,'b':2}
print(*a)
#a b
[序列解包]序列解包没有 **。
>>> a, b, *c = 0, 1, 2, 3
>>> a
0
>>> b
1
>>> c
[2, 3]
- 拆开字典 **a
在输入函数的时候用
def ff(**keyword):
print(keyword)
ff(**{'a':1,'b':2})
#{'a': 1, 'b': 2}
报错
a={"name":1,'bv':2}
print(**a)
#TypeError: 'name' is an invalid keyword argument for print()
-函数传参 引用类型 普通类型
python中的基本类型都是普通类型.数,布尔型,字符串型
除这些之外都是引用类型
程序内存分析网站:pythontutor.com
- 引用类型
传输的时候传输的是地址
l1=[1,2,3,4,5]
l2=l1
l2[0]=0
print(l1)
#[0, 2, 3, 4, 5]
- 普通类型
传输的时候传的是值
a=5
b=a
b=10
print(a)
#5
- 函数传参
传参的本质是赋值操作,如果传递的是引用类型数据,则需要注意是否在函数中对其作了修改
防止做修改,可以在函数内先创建副本:
用:numbers=numbers[:]
或:numbers=list(umbers)
def power(numbers):
numbers=[x**2 for x in numbers]
numbers[3]=3333
return numbers
nums=[1,2,3,4,5]
print(power(nums))
print(nums)
#1, 4, 9, 3333, 25]
#1, 2, 3, 4, 5]
若想让原来的列表被改变,就让函数直接更改(不要生成新的)比如用for循环,就会把这个引用类型直接也改了
def power(numbers):
#numbers=list(numbers)
#numbers=[x**2 for x in numbers]
for i,x in enumerate(numbers):
numbers[i] = x ** 2
# numbers[3]=3333
return numbers
nums=[1,2,3,4,5]
print(power(nums))
print(nums)
#1, 4, 9, 16, 25]
#1, 4, 9, 16, 25]
- 函数也可以引用
函数的本质是函数的地址
def fun():
print("hello world")
f=fun
f()
#hello world
- 函数的嵌套
闭包:函数嵌套函数,外层的函数返回内层函数的地址.
闭包用的时候内层函数不用担心污染外边.
def otter():
def inner():
print('hello inner')
return inner
fo=otter()
fo()
#hello inner
- 函数的作用域
变量的作用域是以函数为单位的
def otter():
a=10
def inner():
print(a)
print('hello inner')
return inner
fo=otter()
fo()
#10
#hello inner
def otter():
a=10
def inner():
a=20
print(a)
print('hello inner')
print(a)
return inner
fo=otter()
fo()
#10
#20
#hello inner
内层函数要访问变量时,会先从自己查找,若找不到,会层层向上查找.内层函数若要新创建值,必须在使用前创建
def otter():
a=10
def inner():
print(a)
print('hello inner')
a = 20
print(a)
return inner
fo=otter()
fo()
#UnboundLocalError: local variable 'a' referenced before assignment
内层函数不能直接更改外层变量,会被认为没有定义.
def otter():
a=10
def inner():
a-=10
print(a)
print('hello inner')
print(a)
return inner
fo=otter()
fo()
#UnboundLocalError: local variable 'a' referenced before assignment
global 代表最外层的变量
a=10
def otter():
a=10
def inner():
global a
a-=10
print(a)
print('hello inner')
print(a)
return inner
fo=otter()
fo()
#10
#0
nonlocal 外面一层变量
若要修改外面一层函数的变量(嵌套层,不一定是最外层的全局变量),用nonlocal
a=30
def otter():
a=10
def inner():
nonlocal a
a-=10
print(a,'inner')
print('hello inner')
print(a)
return inner
fo=otter()
fo()
#10
#0 inner
#hello inner
递归
递归
写递归,首先要确定出口,否则就会无线的调用,直到内存溢出.
递归从后往前思考
高阶函数
把函数作为参数传入函数
函数的本质是地址.
在写大的函数的时候,可以把只让变的部分变化,其他的东西不变:策略模式
handle(func,*param):
return func(*param)
def my_sum(*param):
return sum(param)
print(handle(my_sum,1,2,3,4,5))
#15
系统级的高阶函数
- map函数
map(func,iterable)#该函数会把i特让步了中的数据依次传递给func函数处理,最后把处理结果返回
#map(func,iterable)
def power(x):
return x*x
result=map(power,[1,2,3,4,5])
print(result)#因为result是个生成器,所以没法直接输出结果
print(list(result))
#
- zip()
zip([iterable, ...])
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]
>>> zip(a,c) # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped) # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
[(1, 2, 3), (4, 5, 6)]
- reduce()
累计操作,func函数必须接受两个参数,reduce会把func的运行结果作为一个参数,人后从iterable中再取出一个数据作为另一个参数.
reduce(func,iterable)
from functools import reduce
li=[1,2,3,4,5]
result=reduce(lambda x,y:x*y,li)
print(result)
#120
先把iterable中前两个数据传入x,y,之后把上一次运算的结果当作x,之后在iterable中取一个数据进行计算.
func必须只接受两个参数
- filter()
filter(func,iterable)
柑橘函数func来过滤iterable
将iterable中的数据传入函数func中,如果函数返回True,则保留该数据,否则不保留.
li=[1,2,3,4,5]
result=list(filter(lambda x:x%2==1,li))
print(result)
#[1, 3, 5]
- sorted()
sort(iterable,key=None,reverse=False)
对主句进行排序,key可以用来指定的规则(注意传入的key函数不要加括号,否则就代表函数的调用.),是一个函数.reverse用来指定排序的顺序,默认False,若为True则倒序.
sorted()不会改变原来的数据.
li=[-1,3,6,-10]
print(sorted(li))
print(sorted(li,key=abs))#注意传入的key函数不要加括号,否则就代表函数的调用.
print(sorted(li,key=abs,reverse=True))
print(li)
#[-10, -1, 3, 6]
#[-1, 3, 6, -10]
#[-10, 6, 3, -1]
#[-1, 3, 6, -10]
和.sort的不同
.sort会改变原来的数据
li=[-1,3,6,-10]
li.sort()
print(li)
#[-10, -1, 3, 6]
模块
模块就是一个文件,我们在编写程序时,可以把功能相似的代码放到一个模块中
直接用import导入整个模块,可以用as起别名
import 模块名
import 模块名 as 别名用from----import----导入函数
from 文件名 import 函数名若从两个文件导入同名函数,可以通过as取别名
from food import make_pizza as mp
from pizza import make_pizza
这样就不会出错