背景
在编程语言的大背景下,Python普遍被认为是一门易上手的脚本语言;
而随着Python的应用越来越广泛,仅仅停留在会跑Python程序是不够的;
本篇专栏主要记录一些高阶的用法以及Python语言的一些机制;
Python语言掌握需要具备的能力:
1、深入掌握Python编程机制,掌握高级语法功能,能够解决更加复杂的编程问题;
2、面对常见的Python编程问题明白其原理,能够快速解决;
3、深入理解面向对象和面向函数的作用,写出高质量代码;
4、掌握并发编程、异步编程等高级编程方法,解决高并发问题;
5、掌握Python与C语言的融合,科学加速等性能优化能力;
6、具备企业实战能力,解决复杂性高、性能要求高的任务;
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)
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)
可以看出,节省了大量的代码,使得代码更加友好;
四、生成器及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
print('programming running at {}'.format(datetime.datetime.now()))
collect_results(files)
运行结果:
存在问题:
1、直到所有文件读取完,才开始后续的操作,如果文件过多的话,就会卡在读取这一步;
2、 如果在读取过程中程序中断或崩溃,会导致后面的处理也失效,并且之后也要重新读取;
3、占用内存资源大,将所有文件内容都存在了一个空间中;
使用yied生成器的方法:
def get_all_results(files):
for f in files:
yield count_words(f)
运行结果:
说明:
可以看出,不需要等待全部文件读取完,每次读取后都会对该文件进行处理,节省了空间的同时也提高了安全性;
拓展:
map、filter实际上也是一种生成器的作用,返回一个可迭代对象;
五、装饰器
作用:对函数做改变,并且随时可以取消这个改变;
本质:Fun = anthor(Fun),简写成了@anthor,这也就是改变函数;
代码实战:
def memory(f):
memory.cache = {}
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__':
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的功能很强大,可以对任意数据类型实现多种操作;
拓展:
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))
注意:这里需要注意的是,register()属性支持类型标注在3.7版本更新,一开始用236版本一直无法使用类型标注;
总结
下面列举下本篇相关知识点:
- exce
- match case(python 3.10)
- dataclass(python 3.8)
- yied及生成器
- 装饰器
- PYTHONPATH环境变量配置
- 工具类函数:reduce、cache、partial、singledispatch
以上知识点都是在工程项目中可以使用来优化代码的,特别是环境配置以及生成器的使用;像cache装饰器可以缓存一部分数据,使得程序运行更加高效;
|