1,函数的参数
1.1,查看函数的参数类型
def run(a, *args, b, **kwargs): return a + b
可以通过如下方式查看参数类型:
import inspect k = inspect.signature(run) for i, j in k.parameters.items(): print('{:7}:'.format(i) , j.kind)
输出结果为:
a : POSITIONAL_OR_KEYWORD
args : VAR_POSITIONAL
b : KEYWORD_ONLY
kwargs : VAR_KEYWORD
含义如下:
POSITIONAL_OR_KEYWORD:位置参数或者关键字参数,可以用位置参数或者关键字参数方式传参
VAR_POSITIONAL:可变位置参数,*args
KEYWORD_ONLY:仅限关键字参数,*args或者*后面的,只能用关键字参数方式传参
VAR_KEYWORD:可变关键字参数,**kwargs
POSITIONAL_ONLY:目前不支持
1.2,传参方法
位置参数必须在关键字参数前面!
def test(x, y,z) .......
传参:
位置参数:test(a, b, c) 关键字接收:test(y=a, x=b, z=c) # 关键字参数,可颠倒次序 混合:test(1, z=2, y=6) # 位置参数必须在关键字参数前面,后面2个可以颠倒
1.3,*args,数量可变位置参数
args:序列
*args: 序列中的值
def test(x, *args): print(x, *args) # 1,2,3 print(x, args) # 1,(2,3)
test(1,2,3) # 或test(*[1,2,3])
1.4,**kwargs,数量可变的关键字参数
kwargs:字典
*kwargs: 字典的key
**kwargs:字典的键值对
def test(**kwargs): print(kwargs) # {'name': 'guxh', 'age': 18} print(*kwargs) # name age print(kwargs['name']) # 'guxh'
test(name='guxh', age=18) # 或test(**{'name':'guxh', 'age':18})
1.5,仅限关键字参数
*后面的是仅限关键字参数:
def test(x, *, y): print(x, y) test('a', 'b') # TypeError test('a', y='b') # OK
*args后面的是仅限关键字参数:
def test(*args, y): print(*args, y) test('a', 'b') # TypeError test('a', y='b') # OK
1.6,特殊传参
组合传参,如果name用关键字参数传参,则age必须用关键字参数传参,因为位置参数必须在关键字参数前面。
def test(name, age=18, *args, **kwargs): print(name) # 位置参数或关键字参数,'guxh' print(age) # 位置参数或关键字参数,34 print(args) # 可变位置参数,() print(kwargs) # 可变关键字参数,{'sex': 'f', 'hobby': 'python'}
test('guxh', 34, sex='f',hobby='python') test(name='guxh', age=34, sex='f',hobby='python')
序列传参,字典传参:
def test(x, y):test(*序列),或test(**字典)
def test(*args) : test(*序列)
def test(**kwargs) :test(**字典)
2,防御可变参数
#######################################
待修订
5,内置函数
5.1,递归函数
函数内部调用自己,就叫递归函数
最大递归次数是999次,超过就会报错
例如:
def cal(n):
print(n)
return cal(n+1)
cal(0)
打印到998就报错
递归要有明确结束条件、每次调用要减少问题规模,效率不高
例如:
def cal(n):
print(n)
if int(n/2) > 0:
return cal(int(n/2))
cal(10)
5.2,匿名函数lambda
方式一:
cacl = lambda x:x*3
cacl(3) # 9
方式二:
(lambda x:x*3)(3) # 9
5.3,内置函数概述
1)all(iterable):全部为真返回True,否则返回False
2)any(iterable):任意为真返回Ture,否则返回False
3)ascii(object):没什么用
4)bin(x):将整数转换为二进制数
5)bool(x):判断真假
6)bytes ('abcde', encoding='utf-8'): 把字符串变成字节码,这时如果赋给a,a[0]会显示97
7)bytearray('abcde', encoding='utf-8'):与bytes的区别是,字节码变成可以修改的了
8)callable(object):判断对象是否可以调用,后面可以加()的就可以调用
9)chr(i):输入一个数字,返回ascii对应的字母符号;ord(x)与其相反,输入字符,返回数字
10)classmethod(function):
11)compile(......):用不到,底层用于编译,结合exec可以实现动态导入功能(相当于import)
12)complex():用不到,复数
13)delattr(object, name)
14)dir([object]):看object有哪些方法,例如a = {}, dir(a)看字典a有哪些方法
15)divmond(a, b):相除,并返回(商,余数)
16)enumerate(iterable, start=0):迭代index和value
17)eval(expression, globals=None, locals=None):反序列化,把字符串变字典/列表等,a = '{}'; eval(a) # 输出{}
把字符串变成对象,如果字符串是可执行的命令,还可以执行并返回结果
例如:
s = 'locale.getpreferredencoding()'
res = eval(s)
总结:序列化是对象变字符串,反序列化是字符串变对象(注意函数也是对象,python中一切皆对象)
18)exec(objects[,globals[,locals]]):动态调用?
19)filter(function, iterable):lambda无法处理for循环,只能做简单的三元运算,lambda一般都结合fiter、map、reduce使用,详见5.4
20)float()
21)format()
22)frozenset([iterable]):把list或者集合变成不可变
23)globals():用不到,返回程序内所有key,value
24)hash(object):计算哈希值
25)hex(x) : 转为16进制
26)id(object):打印ID
27)input()
28)class int
29)isinstance()
30)issubclass():判断是否子类
31)iter()
32)len(s):判断长度
33)locals():用不到,打印局部变量
34)max():返回最大值
35)min():返回最小值
36)memoryview(obj):用不到
37)next():迭代器next()
38)class object:python一切皆对象
39)oct(x):转8进制
40)open(file, mode='r', encoding=None):打开文件
41)ord():与chr()相反
42)pow(2,8):返回2的8次方
43)print()
44)range()
45)repr(obj):把系统输出的东西转换成字符串
46)reversed(seq):翻转序列,python3中,反转后是迭代器,可以这样赋值获取:lista = [1,2,3,4,5,6,7,8,9]; listb = [i for i in reversed(lista)]
47)round(1.333, 2):1.333保留2位小数
48)class set:集合
49)setattr:非常重要
50)slice:没什么用,切片,d=range(20); d[slice(2,5)] 等价于 d[2:5]
51)sorted:排序,可对序列排序,如果想对字典进行排序需要先将字典转换为列表:
dict = {10:20, 22:2, 1:99, 50:21, 37:9}
print(sorted(dict)) # 默认对key排序[1, 10, 22, 37, 50]
print(sorted(dict.items())) # 按key排序[(1, 99), (10, 20), (22, 2), (37, 9), (50, 21)]
print(sorted(dict.items(), key=lambda x:x[1])) # 按value排序[(22, 2), (37, 9), (10, 20), (50, 21), (1, 99)]
52)staticmethod(function):
53)class str
54)sum:求和
55)supper:非常重要,继承
56)tupple([iterable]):转换为元组
57)class type(obj):
58)vars([obj]):用不到,返回一个对象的所有属性名
59)zip:多组数据一起迭代,长度如果不一致按照数据最少的来
60)import:import 'decorator' 等价于 __import__('decorator')
5.4,filter、map、reduce
map/filter + lambda = 列表推导式
foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
1)filter滤出符合的数据(基于bool过滤)
过滤出来的内容,python2里是iterable,python3里是iterator,列表推导式都是iterable
例子一:foo中过滤出x % 3 == 0 的数据:
filter(lambda x:x%3 == 0, foo) # 3是iterator,2是iterable,[18, 9, 24, 12, 27]
例子二,将大于10的过滤出来
filter(lambda x:x>10, foo) # 3是iterator,2是iterable,[18, 22, 17, 24, 12, 27]
等价的列表推导式:
[i for i in foo if i >10] # 3和2都是iterable
2)map对每项都运算下
同filter,python2里是iterable,python3里是iterator,列表推导式都是iterable
例子一,foo中所有数据执行x*2+10:
map方法:map(lambda x: x * 2 + 10, foo) # [14, 46, 28, 54, 44, 58, 26, 34, 64]
列表推导式方法:[i:i*2+10 for i in foo]
例子二:将列表数值转为字符串:
map方法:map(str,foo) # ['2', '18', '9', '22', '17', '24', '8', '12', '27']
列表推导式方法:[str(i) for i in foo]
注意:map函数返回的是一个class map,可以通过list(map)把结果打印出来
3)reduce不停迭代
python2.7可以直接用,python3需要import functools
functools.reduce(lambda x,y:x+y, foo) /不停迭代运算,得到139
4)filter和map应用差别举例
filter满足条件的过滤出来,map所有项目全都会运算一边,例如有一个text,需要有一个list里去匹配的话,
fdx_list_temp=filter(lambda x:re.search(r'\D(%s)(\Z|\D)'%x,element).group(1) if re.search(r'\D(%s)(\Z|\D)'%x,element) else None,list)
list=['301','302','303','304','305']
element='aaaaaa.303.aaaaaaaaaa'
如果是filter,得到['303']
如果是map,得到[None,None,303,None,None]
5)map、filter的列表推导等价
要求找出list中能被2整除的数,并且执行平方运算
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
q1 = [] # 方法一:最原始方法
for element in list:
if element % 2 == 0:
q1.append(element**2)
q2 = [x**2 for x in list if x % 2 == 0] # 方法二:推导列表
q3 = map(lambda x: x**2, filter(lambda x: x%2 == 0, list)) # 方法三:map/filter
5.5,input和raw_input
1)输入
input():只有python2.x有,用户输入什么就是什么,比如输入abc,python2.x当作是abc变量,除非输入“abc”才当字符串,鸡肋不要去用它
raw_input():将用户输入任何内容作为原始数据,在python3.x中,input就是raw_input的意思
例如如果要输入字符串,用input需要加“”,用raw_input不需要加
如果向让输入不可见,可以import getpass,然后password = getpass.getpass("password:") # 注意pycharm中getpass不管用,要在cmd环境下运行
2)格式化输出
输出方法一:字符串拼接,例如:
'''name is''' + name
输出方法二:%s占位符,先占位,再补上,例如:
"my name is %s, age is %s"%('guxh', '19')
常用的参数有,%s字符串,%d 整数,%f 浮点数
输出方法三:用{name},例如:
"my name is {name}, age is {age}".format(name='guxh', age=19) # {age: .2f}可以设置输出age格式,浮点保留2位
"my name is {name}, age is {age}".format(**{'name': 'guxh', 'age': 19})
输出方法四,用{}或者{index},例如:
"my name is {}, age is {}".format('guxh', 19) # {:.2f},age浮点保留2位
"my name is {0}, age is {1}".format('guxh', 19) # {1:.2f},age浮点保留2位
格式化参数:
^, <, > 分别是居中、左对齐、右对齐,后面带宽度,
: 号后面带填充的字符,只能是一个字符,不指定则默认是用空格填充。
+ 表示在正数前显示 +,负数前显示 -; (空格)表示在正数前加空格
b、d、o、x 分别是二进制、十进制、八进制、十六进制
举例: '{:@>18,.2f}'.format(70305084.0) # >右对齐,@缺失部分用@填充,18固定宽度,','千分位,'.2'浮点精度2,f浮点数声明
输出:@@@@@70,305,084.00
5.6,替换函数
str.replace
strip
re.sub
6,高阶函数
满足下面两个条件之一的就叫高阶函数:
a,把一个函数名当作实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
例如:def add(-5, 6, abs) # abs是内置函数取绝对值
b,返回值中包含函数名(不修改函数的调用方式)
例如:return abs
即:高阶函数 = 参数是函数名,或者返回值包含函数名
这2个条件都严格遵循函数即变量
备注:函数的门牌号就是内存地址,有了门牌号(内存地址)加上小括号就可以运行内存里的函数体,获取其返回值,有()传的是返回值,没有()传的是门牌号
def bar():
print('the result...')
test(bar) # 把门派号,即地址传给test()函数
test(bar()) # 把bar()的返回值,即None传给test()函数
条件a - 打印函数变量地址:
def bar(): # bar是个门牌号,bar()是执行门牌号指向的函数体
print('in the bar')
def test(func):
print(func) # 打印出了bar的门牌号(地址)
func() # 执行bar()
test(bar) # 把bar作为变量传递给test()函数
条件b - 打印函数变量地址:
def bar():
time.sleep(3)
print('in the bar')
def test2(func):
print(func) # 打印了bar的门牌号
return func
bar=test2(bar) # 新的bar覆盖了原来旧的bar,新的bar去test2执行了2步:打印旧bar门牌号,返回旧bar的门牌号
bar() # 执行新的bar,共2步:打印旧bar门牌号,执行旧bar程序,等同于test2(bar)()
test2相当于装饰器作用,不改变bar调用方式,不改变bar源代码
条件a - 统计函数运行时间:
def bar():
time.sleep(3)
print('in the bar')
def test(func):
start_time = time.time()
func()
stop_time = time.time()
print('the running time of func is %s'%(stop_time - start_time))
test(bar) # test有点类似于装饰器,给bar()附加了其他功能,统计其运行时间,但因为调用方式改变了,用的是test(bar),而不是bar(),所以不是装饰器
条件b - 统计函数运行时间:
def deco(func):
start_time = time.time()
func() # 第一遍打印in the test2
stop_time = time.time()
print(('running time of func is %s')%(stop_time - start_time))
return func
def test2():
time.sleep(2)
print('in the test2') # 第二遍打印in the test2
test2 = deco(test2) # 这时调用deco函数时打印第一遍
test2() # 这时调用test函数时打印第二遍
本来想统计下test2运行的时间,但存在的问题是,in the test打印了2遍
7,嵌套函数
函数内部再定义一个函数,即def内部再def一个函数
函数内部调用一个函数不算函数嵌套
8,函数式编程
注意函数式编程不是我们认为的函数
更接近数学运算,通过一堆函数来回调用,得到结果
函数式编程只要输入是确定的,输出也是确定的
代码简介,但是难以阅读
eg:var result = subtract(multiply(add(1,2), 3), 4);
9,外置函数
9.1,时间戳
def timeformat(item): # 改时间戳
local_timeArray = time.strptime(item, "%Y-%m-%d %H:%M:%S")
local_timeStamp = int(time.mktime(local_timeArray))
return round(float(local_timeStamp)/3600, 2) # 对时间戳换算到小时并保留2位
9.2,SYS和OS库文件
sys.path # 打印python环境变量
sys.argv # pycharm打印绝对路径,cmd打印相对路径
os.system("dir") # 调用windows dir命令,打印当前目录,不保存结果,成功则返回0
os.popen('dir') # 调用windows dir命令,打印当前目录,并保存结果,成功则返回地址,可以通过read()去取内容
os.mkdir('new_dir') # 调用windows mkdir命令,创建新目录
9.3,Sys.argv[ ]
是一个列表,里面的项目为用户输入的参数
例如 python test.py 1 2 3
argv = ['test.py', '1', '2', '3']