背景

在编程语言的大背景下,Python普遍被认为是一门易上手的脚本语言;

而随着Python的应用越来越广泛,仅仅停留在会跑Python程序是不够的;

本篇专栏主要记录一些高阶的用法以及Python语言的一些机制;

Python语言掌握需要具备的能力:

1、深入掌握Python编程机制,掌握高级语法功能,能够解决更加复杂的编程问题;

2、面对常见的Python编程问题明白其原理,能够快速解决;

3、深入理解面向对象和面向函数的作用,写出高质量代码;

4、掌握并发编程、异步编程等高级编程方法,解决高并发问题;

5、掌握Python与C语言的融合,科学加速等性能优化能力;

6、具备企业实战能力,解决复杂性高、性能要求高的任务;

Python对比其他语言的运行速度:

python培训心得与总结 python系统培训_Python

知识点

一、exce使用案例,结合String做的一种编程方式

def decision_process(conditions, outs):
    base_string = f"if string.startswith('{conditions[0]}'): print('{outs[0]}')"    

    for c, out in zip(conditions[1:], outs[1:]):
        base_string += f"\n\telif string.startswith('{c}'): print('{out}')"    


    return base_string


def create_func(conditions, outs):
    return f"""def complexit_if(string):
\t{decision_process(conditions, outs)} 
    """

programming = create_func(['0', '1', '2'], ['none', 'first', 'second'])

exec(programming)				# 执行这一行创建了一个函数对象complexit_if
exec("complexit_if('001231')")	
exec("complexit_if('112311')")
exec("complexit_if('201231')")

说明:这个案例主要是想表示,exec可以作为一种执行代码的函数,也体现了Python的解释型语言;

拓展:还有一种eval()的函数方式,也可以对string进行执行,并且得到的是返回值;

二、Python3.10新特性——match case

Python3.10之后,引入了一种模式匹配的方法,并且具有更好的泛型能力;

下面简单创建一个json的字典样例:

parsed_json = {
        "Age": 19,
        "user_id": "uuid1231241",
        "goods_info": {
            "price": 100,
            "createtime": 2022
        }
    }

接下来用match case进行匹配:

match parsed_json:
        case {"Age": age, "user_id": userd_id, "goods_info": {"price": p, 'createtime': time_}}:
            print(f"{age} with id {userd_id} bought {p} goods")
        case {'Age': age, 'user_id': userd_id, "action_info": {"last_login": p}}:
            print(f"{userd_id} with age {age} last login is {p}")
        case _:
            print("None")

结果当然是输出第一个匹配的对象,可以看出模式匹配还是很强大的,还可以对其他的类型进行匹配;

三、一种初始化类的快速方式——dataclass

首先正常情况下我们定义一个类并且初始化:

class OldPerson:
    def __init__(self, name="Tom", age=10, location=10.0, weight=20.0):
        self.name = name
        self.age = age
        self.location = location
        self.weight = weight

    def __repr__(self):
        return f"Person(name={self.name}, age={self.age}, location={self.location}, weight={self.weight})"

从上面代码可以看出来,其中的过程是有些复杂的,特别是对于参数较多或者复杂的类别来说;

下面介绍一种新的定义类的方法:

from dataclasses import dataclass

@dataclass
class Person:
    name: str = ""
    age: int = 18
    location: float = 10.0
    weight: float = 20.0

person = Person()
person.name = "Jack"
print(person)				# Person(name='Jack', age=18, location=10.0, weight=20.0)

可以看出,节省了大量的代码,使得代码更加友好;

四、生成器及yied的作用

通常情况下我们程序处理都是面向过程的,下面模拟一个读取文件的操作,代码如下:

# 导入头文件
import time
from collections import defaultdict
import datetime

# 设定处理一个文件的操作
def count_words(filename):
    counts = defaultdict(int)    
    time.sleep(1)	# 假设整个流程需要一秒
    return counts

# 传入一个文件列表,对其中的每个文件都进行上述操作
def get_all_results(files):
    results = []
    for f in files:
        results.append(count_words(f))	# 遍历列表中的每个文件,当全部遍历完后才会返回结果
    return results

# 对得到的数据做处理
def collect_results(files):

    for c in get_all_results(files):
        print('get one {}'.format(datetime.datetime.now()))		# 假设处理一次就打印一次处理的时间

if __name__  == '__main__':
    files = ['some_file'] * 10		# 假设有10个文件
    print('programming running at {}'.format(datetime.datetime.now()))		# 程序开始运行的时间
    collect_results(files)		# 开始处理

运行结果:

python培训心得与总结 python系统培训_python培训心得与总结_02

存在问题:

1、直到所有文件读取完,才开始后续的操作,如果文件过多的话,就会卡在读取这一步;

2、 如果在读取过程中程序中断或崩溃,会导致后面的处理也失效,并且之后也要重新读取;

3、占用内存资源大,将所有文件内容都存在了一个空间中;

使用yied生成器的方法:

# 只需要在处理文件部分做修改
def get_all_results(files):
    
    for f in files:
        yield count_words(f)	# 使用yield返回结果,这个函数也被作为一个生成器
    
    # return (count_words(f) for f in files)	# 也可以直接返回一个可迭代对象,也是一个生成器

运行结果:

python培训心得与总结 python系统培训_Python_03

说明:

可以看出,不需要等待全部文件读取完,每次读取后都会对该文件进行处理,节省了空间的同时也提高了安全性;

拓展:

map、filter实际上也是一种生成器的作用,返回一个可迭代对象;

五、装饰器

作用:对函数做改变,并且随时可以取消这个改变;

本质:Fun = anthor(Fun),简写成了@anthor,这也就是改变函数;

代码实战:

# 首先定义一个函数,来修改传进来的函数
def memory(f):
    memory.cache = {}  # function attribute

    def _wrap(n):
        if n in memory.cache:
            print('hit {}'.format(n))
            return memory.cache[n]
        else:
            r = f(n)
            memory.cache[n] = r
            return r
    return _wrap

@memory
# 实现一个斐波那契数列
def fib(n):
    return fib(n - 1) + fib(n - 2) if n >= 2 else 1


if __name__ == '__main__':
    # fib = memory(fib)     // 使用装饰器相当于执行这行代码
    print(fib(10))

说明:

上述就是一个装饰器的使用,起到一个缓冲机制的作用,使得函数fib运行速度更加高效;

六、PYTHONPATH环境变量

这里需要介绍一个环境变量:PYTHONPATH

如果将自定义的一个py文件的路径放到这个环境变量中,代码如下:

export PYTHONPATH=${PWD}

那么在别的路径下,可以直接引用该环境变量路径下的包;

作用:十分便捷的引入外部工具包的方式,避免了一些工程文件的复制以及复杂的文件调用;

七、一些实用的工具函数

1、reduce

作用:将一个集合中的所有元素依次执行某个操作;

代码实现:

from functools import reduce

some_lists = [
    [1, 2],
    [3, 5],
    [5, 6, 7, 1, 10.1, 11.1],
    [121.4, 11.34],
    [11.31, 1921, 321.],
]

print(reduce(lambda a, b: a + b, some_lists))

说明:

以上就是对多个数组进行相加的实现,reduce的功能很强大,可以对任意数据类型实现多种操作;

拓展:

  • operator库
import operator

这是一个运算符操作的汇总库,可使用的一些操作在其内置的文件中有进行说明,下面是其包含的操作符方法:

python培训心得与总结 python系统培训_生成器_04

2、cache

作用:

起到一个保存缓存数据的作用,对一些重复数据的结果进行保存,提高程序运行的效率;

代码示例:

from functools import cache

@cache
def fib(n):
	return fib(n - 1) + fib(n - 2) if n > 2 else 1

说明:以上代码实现了一个斐波那契数列,用cache工具包能提高其运行效率;

如果想要指定缓存多少个数据,可以用lru_cache这个库,本质上cache也是调用这个库函数;

from functools import lru_cache

@lru_cache(maxsize=2**8)
3、Partial

作用:

中文含义为偏函数,是指将一个函数变为有默认值的函数;

代码示例:

from functools import partial

def load_info(id, name, age, sex):
  print(sex)

# 定义默认参数的值
id1_config = {
    "id": '001',
    "name": "hero"
    }

# 创建一个新函数,设定默认参数
load_info_1 = partial(load_info, **id1_config)
load_info_1(age=10,sex="男")

说明:这个工具能够起到简化代码的作用,不需要每次传入相同的参数,只需要创建一个具有固定参数的对象即可;更好的体现了面向对象编程这个概念,并且能够优化内存空间;

4、singledispatch

作用:

中文含义为单例分发模式,往往一个函数可以接收不同类型的参数,如果想修改不同类型参数时的实现,往往需要改变函数体,也不便于维护;单例分发模式可以在不修改源代码的情况下,将实现分发出去,更符合开发逻辑;

代码示例:

from functools import singledispatch

@singledispatch
def multiply(arg1, arg2):
  pass

@multiply.register
def _(arg1:str, arg2:str): return arg1+arg2

@multiply.register
def _(arg1:int, arg2:int): return arg1*arg2

print(multiply(1, 2))		# 2

注意:这里需要注意的是,register()属性支持类型标注在3.7版本更新,一开始用236版本一直无法使用类型标注;

总结

下面列举下本篇相关知识点:

  • exce
  • match case(python 3.10)
  • dataclass(python 3.8)
  • yied及生成器
  • 装饰器
  • PYTHONPATH环境变量配置
  • 工具类函数:reduce、cache、partial、singledispatch

以上知识点都是在工程项目中可以使用来优化代码的,特别是环境配置以及生成器的使用;像cache装饰器可以缓存一部分数据,使得程序运行更加高效;