guxh的python笔记:函数基础

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']

猜你喜欢

转载自www.cnblogs.com/guxh/p/10252557.html
今日推荐