python常用函数学习总结

1.如何使用递归?

  • 怎么递归? natural recursion
  • 什么时候结束? 终止条件

参考the little scheme

已有的结论是函数名字可以调用 新的结论:

  1. 函数名字可以赋值,
  2. 函数可以嵌套,于是出现了高阶函数!
  3. 也就是函数名字作为函数参数,可以作为返回值
def fun():
    def init():
        return 8;
    return init;
letlei=fun();
print(f"hello,{letlei()}")
def fibo(n):
    if(n==0):
        return 0
    if(n==1):
        return 1
    return fibo(n-1)+fibo(n-2)
print(fibo(10))

2. python filter的使用

结论:filter可以过滤一个容器的元素,但不会改变元素内容

迭代器批次把内容从容器放出来(使用一个,则倒出一个到内存),列表全部把内容从容器倒出来(都放入内存中)

def fun2filter(str):
    if( str != 'a'):
        return str
ret = filter(fun2filter, ['a','b','c'])
print(f" filter Object is {ret}")
print(f" force change to list Object is {list(ret)}")

3. python map的使用

结论:map可以处理一个容器的数据,会改变元素内容 很关键,fitler只会过滤数据,而不会修改元素,map则可以逐个修改数据!

def fun2map(str):
    return str+"added"

ret1 = map(fun2map,['a','b','c'])
#ret1 = filter(fun2map,['a','b','c']) 不会起作用的!!!!他只会过滤,不会修改!

print(f"map object is {ret1}")

<2022-01-16 周日 22:38>测试通过

4. python reduce使用

结论: reduce只返回序列(或者列表)的求和运算? 把一个序列变为一个值,一个结论! reduce只会返回最终解!阶乘也很好用!

reduce本质就是斐波那契数列 计算阶乘也很方便

from functools import reduce
def fun2reduce(x,y):
    return x+y

def funM2reduce(x,y):
    return x*y
sum1=reduce(fun2reduce,[1,2,3,4,5])
sum2=reduce(lambda x,y: x+y, [1,2,3,4,5])
sum3=reduce(funM2reduce,[1,2,3,4,5])
sum3=reduce(funM2reduce,range(1,10))
print(f"reduce function f is  {sum1}   pk  {sum2} pk {sum3}")

阶乘:

print(reduce((lambda x,y:x*y),range(1,5)))
24

5. 什么是闭包?

结论: inner是一个闭包,符合两个条件,1. inner是一个内部函数,2. inner调用外部环境的一个变量 即 闭包=内部函数+内部函数定义时的环境变量

def outer():
    x=10
    def inner(): ## 1. 内部函数
        print(x) ## 2. 调用内部函数外部环境变量x
    return inner

outer()()
fout2inner = outer()
print(f"测试闭包的功能 {fout2inner()}")

结论:基于闭包思想 及装饰器思想解决代码重复问题

6. python抽样

结论:通过choice,sample,randrange,randint函数实现抽样功能

import random

print(f"random.random() = {random.random()}")
print(f"随机生成1个值random.randint(1,8) = {random.randint(1,8)}")
print(f"随机生成1个值random.randrange(1,8) = {random.randrange(1,8)}")
print(f"随机选取序列1个值 choice(序列)=sampe(序列,1):random.choice('hello') = {random.choice('hello')}")
print(f"随机选取序列1个值:random.choice(['123',4,[12,3,4]]) = {random.choice(['123',4,[12,3,4]])}")
##
print(f"随机选取序列多个值,sampe(序列,个数):random.sample(['123',4,[12,3,4]],2,'34') = {random.sample(['123',4,[12,3,4]],2)}")

def v_code():
    code=''
    for i in range(6):
        ## choice形成序列
        ## choice很有用的
       add=random.choice([random.randrange(10),chr(random.randrange(65,90)),chr(random.randrange(97,122))])
        ## 转换为string
       code += str(add)
    print(code)

# def v_codes(sampleNum):
# bug因为random出来的是一个结果
    # print(random.sample([random.randrange(10),chr(random.randrange(65,90)),chr(random.randrange(97,122))],sampleNum))

v_code()

7. 什么是生成器? 什么是迭代器?

结论:生成器(列表 list, tuple, string, dict)都是迭代器(满足两个条件:1. 有iter方法,2. 有next方法),迭代器不一定是生成器

# 列表生成器 方式
a=[x*2 for x in range(1,10)]
# 迭代器
b=(x*2 for  x in range(10000))
print(next(b))
print(next(b))
print(next(b))

8. yield的作用?

结论: 只要有yield的都是迭代器函数对象 foo()(不加载到内存),如果没有就是普通函数加载到内存了

def foo():
    print("ok")
    yield 1
    print("ok2")
    yield 2

g= foo()  ## foo() 带括号是生成器对象
print(g)

## 调用生成器函数对象
print(next(g))
## 可以控制执行次数!
print(next(g))

结论:迭代写法和同时写法有所不同, 要注意一句话写完和两句话写完是不一样的,以为before的值已经发生了修改!

## 0 1 1 2 3 5 8 13
## 同时和并行什么区别? 同时就是同一条语句(有点并行线程的感觉,并发执行), 保证before不更新
## 不同时就是分成两部执行,分成先后,有迭代顺序, 先后写before会更新
def fib(max):
    n,before,after=0,0,1
    while n<max:
        print(f"n={n}, before={before} after={after}")
        # before=after
         yield(before) ## 变成生成器对象函数
       # after=before+after  ## 实际上after ={before}+after before不能更新
        before,after=after,before+after
        n=n+1
    print(f"fib({max}) = {after}")

fib(5)

结论:改造为生成器函数对象

def fib(max):
    n,before,after=0,0,1
    while n<max:
        print(f"n={n}, before={before} after={after}")
        # before=after
        # after=before+after  ## 实际上after ={before}+after before不能更新
        yield(after) ## 变成生成器对象函数
        before,after=after,before+after
        n=n+1
    print(f"fib({max}) = {after}")

g=fib(5)

next(g)
next(g)
next(g)

结论: yield可以通过send方法进行函数变量赋值控制, 第一次必须先进性赋值next(b) 或者通过b.send(None), b.send(None)等效于next(b)

一次send等效于一次next,即执行一次yield

  def far():
      print('ok1')
      count=yield 1
      print(count)
      count2=yield 2+count
      print('ok3'+count2)
      yield 3

  df=far()
  df.send(None)
#df.send(None) ## 第一次必须是df.send(None) 或者先执行一次next(df)

  df.send(3)
  print(df.send('2----'))
  # next(df)

9.如何使用OS模块

结论: 文件目录相关操作可以参考OS模块

import os
print(os.getcwd())
print(os.listdir())

print(os.stat('./'))
print(os.pathsep)
print(os.sep) ## 路径分割附
print(os.environ)
print(os.path.dirname('c:/testRandom.py'))
print(os.path.basename('c:/testRandom.py'))

10. 如何使用hashlib

结论: 通过hashlib创建解密和加密 1、什么叫hash:hash是一种算法(不同的hash算法只是复杂度不一样)(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算法接受传入的内容,经过运算得到一串hash值 2、hash值的特点是(hash值/产品有三大特性:)

  md52=hashlib.md5()
  print(md52)
  md52.update('hell word'.encode('utf-8'))
  md52.update('hell word'.encode('utf8')) ## python3只有unicode和 ,默认不是utf-8
  md52.digest()
  md52.hexdigest()

11. 如何扩平台编码

结论: 扩平台运行可以参考sys模块

print(f" sys.argv= {sys.argv}")
print(f"sys.path = {sys.path}")
print(f"sys.platform = {sys.platform}" )
print(f"sys.maxsize = {sys.maxsize}" )
print(f"sys.stdout.write('Please:') = {sys.stdout.write('Please:')}" )
#正常退出,不执行下面代码
# print (sys.exit(0))

# if sys.platform=='win32':
#     os.system('dir') ## 执行系统命令
# else:
#     os.system('ls')

12. 如何使用RE模块

结论:通过re模块进行正则匹配 https://docs.python.org/zh-cn/3/library/re.html

需要明确常用的正则元素、字母、数值、元数据( * + ? \d{3,} [abA-Z] ||| . \d \s \S \w \W )等! 要注意正则零宽断言和捕获方面的使用

如果在python中使用正则,想要直接使用正则语法则注意在模式表达式前面加小写r,如果不加小写r,表示先试用python解析字符串,然后再把解析后的内容传给正则表达式进行解析。

  import re

  ## 返回所有匹配对象,并放在一个列表中
  print(re.findall(r'\\','df\\b'))
  ## \元字符在python中有特殊用途
  print(re.findall('\\\\','df\\b'))

  ## search 返回第一个匹配对象,并且可以通过group进行调用
  #ret=re.search(r'(?P<id>\d{3})/(?P<name>\w{3})','weekdydtt123/ooo')
  ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weekdydtt123/ooo')
  print(ret.group('id'))
  print(ret.group('name'))
  ## match 返回第一个匹配对象,并且可以通过group进行调用
  ## 但是从第一个字符开始找, 如果第一个字符就不匹配就返回None, 不继续匹配. 用于判断字符串开头或整个字符串是否匹配,速度快。
  ## match 自带^光环,所以速度很快
  # ret=re.match(r'(?P<id>\d{2})/(?P<name>\w{3})','weekdydtt123/ooo')
  # print(ret.group('id'))
  # print(ret.group('name'))


  ## re.compile 编译生成Pattern对象 可重复使用Pattern,pattern对象可调用findall, search and match
  pat= re.compile('ab')  ## 提出一般模式, 基于该模式可运用到不同的场景下!
  ret1=pat.findall('abcd abc gd')
  ret2=pat.findall('acd abc gd')
  ret3=pat.match('abc db ab')
  ret4=pat.search('abc db ab')
  print(ret1)
  print(ret2)
  print(ret3.group())
  print(ret4.group())
  print(ret4.group())

13. 如果有配置文件?

结论:通过configparser模块生成和读取配置文件

写入文件:

import  configparser

config=configparser.ConfigParser()
config["DEFAULT"]={
    'ServerAliveInterval': '45',
    'Compression':'yes',
    'CompressionLevel': '9'
}

config['bitbucket.org']={}
config['bitbucket.org']['user']='hg'
# config['bitbucket.org']={'user':'hg'}
config['topsecret.server.com']={}
topsecret=config['topsecret.server.com']={}
topsecret['Host Port']='50222'
config['DEFAULT']['ForwardX11']='yes'

with open('example.ini','w') as configfile:
    config.write(configfile)

读取文件:

import  configparser
config=configparser.ConfigParser()

config.read('example.ini')

print(config.defaults())
print(config.sections())
print(config['bitbucket.org'])
print(config['bitbucket.org']['user'])
print(config['DEFAULT']['Compression'])
Related
叶昭良
叶昭良
Engineer of offshore wind turbine technique research

My research interests include distributed energy, wind turbine power generation technique , Computational fluid dynamic and programmable matter.