几个你所应该知晓的python3特性[python3.7及前版本]

几个你所应该知晓的python3特性[python3.7及前版本]
Page content

时至今日,python2大限已到,且python3对各类原有框架及模块都有了非常好的支持。下面给大家简单介绍一些或许你不常用的,但你应该知道的那些 新特性。

模板语法 f-strings

首先我们或许比较习惯使用.format()

nums = 4
name = 'tasks'
time = 5.6
'{} {} done, used {}s'.format(nums,name,time)

4 tasks done , cost 5.6s

接下来我们使用'f'模板语法, 有没有发现可读性提高了不少!

f'{nums+1} {name} done, used {time}s'

5 tasks done , cost 5.6s

解包扩展

以前我们更新一个字典或许需要这样


dict_a = {'a':'b'}
dict_b = {'c':'d'}
dict_a.update(dict_b)

# output

{'a': 'b', 'c': 'd'} # dict_a

而在python3中我们可以这样, *操作tuplelist 等同理

{**dict_a,**dict_b}

# output

{'a': 'b', 'c': 'd'}

输入预提示

为了增强函数及返回值的类型提示,我们可以这样来定义一个poc函数, 提示urls变量是成员为str的元祖、payloadPAYLOAD类, 而超时时间为float类型, 默认值5秒,最终返回结果将为一个布尔值。


from typing import Tuple

class PAYLOAD:
    ...

def poc(urls: Tuple[str], payload: PAYLOAD, timeout: float = 5) -> bool:
    ...
    return is_vul

async 与await 关键字及asycio

这里通过一个协程并发的案例来作简单说明。这里设定两个任务。

  • 任务1: 执行睡眠2秒
  • 任务2: 执行睡眠1秒
import asyncio
import logging

logging.basicConfig(level=logging.DEBUG, format="[%(asctime)s]%(message)s")
log = logging.getLogger()

async def sleep(task, times: int):
    log.info(f"task {task} start.")
    await asyncio.sleep(times)
    log.info(f"task {task} done.")

async def main():
    await asyncio.gather(
        sleep(1, 2), 
        sleep(2, 1)
    )

asyncio.run(main())

# output

[07:30:09,109]Using selector: KqueueSelector
[07:30:09,110]task 1 start.
[07:30:09,111]task 2 start.
[07:30:10,113]task 2 done.
[07:30:11,115]task 1 done.

从输出结果我们可以看到,整个过程只花费了两秒钟。

路径遍历增强

现在我们使用os.scandir()来代替原有的os.walk(), 且其的执行效率将提高3至5倍。

for entry in os.scandir(path): # 扫描path路径
    if not entry.name.startswith('.') and entry.is_file(): # 过滤掉文件夹
        print(entry.name) # 打印出文件名

枚举Enum

假设我们设定一组星期数据。

Sun = 1
Mon = 2
...
Sat = 7

并用来判定一周的第N天是周几的时候,我们可以这么写

days = int(N)

if(N==Mon){
    print('Mon')
}
else if(N==Tue){
    print('Tue')
}
...
else{
    print('Sun')
}

但是我们有没有发现这样写有点 麻烦呢, 于是我们将它改为enum对象, 是否有变得简单很多呢~

from enum import Enum, unique

@unique
class week(Enum):
    Sun = 1
    Mon = 2
    ...
    Sat = 7

week(1).name # Sun

print(week(7)) # week.Sat

week.Sun.value == 1 # True

lru_cache

这是一个可以为函数提供缓存功能的装饰器,在下次以相同参数调用时直接返回上一次的结果。用以节约高开销或I/O函数的调用时间。

例如我们可以用以高效计算斐波那契数列。

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

[fib(n) for n in range(32)]


# 常规操作
# python3 test.py  1.85s user 0.03s system 98% cpu 1.915 total 

# lru_cache
# python3 test.py  0.04s user 0.02s system 90% cpu 0.066 total

在未加上@lru_cache(maxsize=None)时使用了 1.91秒, 而在加上之后只花费了 0.06秒。

数据类 Data classes

以前我们要定义一个类或许需要这样


class food:
    def __init__(self, name: str, overdue: bool = False) -> None:
        self.name = name
        self.overdue = overdue

class animal:
    def __init__(self, name: str, age: int = 1) -> food:
        self.name = name
        self.age = age

    def eat(self, thing: food) -> bool:
        if not thing.overdue:
            return True

meat = food('meat')
dog = animal("dog", 1)
dog.eat(meat)

而现在我们可以这样, 它将帮你自动完成__init__,__repr__,__eq__等方法。

from dataclasses import dataclass

@dataclass
class food:
    name: str
    overdue: bool = False

@dataclass
class animal:
    name: str
    age: int = 1

    def eat(self, thing: food) -> bool:
        if not thing.overdue:
            return True

meat = food('meat',True)
dog = animal("dog", 1)
dog.eat(meat)

# output

False