Back to prev

Python Documentation Read

Dec 1, 2021
Linkang Chan
@Jesse Chan

本篇为一个纯笔记,用户记录阅读 python 手册里面的相关内容,python 的手册中总能发现一些非常不错的技巧,这让在写 Python 程序的时候,更加纯粹。

DataClasses

这个包主要是通过装饰器来为用户自定义的类自动增加一些特殊的函数,比如__init__或者__repr__等。这个库会让写类变得更加简单和可控。一些例子:

from dataclasses import dataclass, field, astuple, asdict

@dataclass(order=True)
class Person:
    name: str
    gender: str
    age: int
    sort_index: int = field(init=False, repr=False)

    def __post_init__(self):
        self.sort_index = self.age

print(dir(Person))

p1 = Person("a", "z", 10)
p2 = Person("b", "m", 12)

print(p1, p2)
print(astuple(p1))
print(asdict(p2))
if p1 < p2:
    print(True)

输出:

['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__post_init__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
Person(name='a', gender='z', age=10) Person(name='b', gender='m', age=12)
('a', 'z', 10, 10)
{'name': 'b', 'gender': 'm', 'age': 12, 'sort_index': 12}
True

上面例子中展示了大部分的 dataclass 的功能。 在定义类的时候,可以通过order=True来让类的属性按照添加的顺序排序。这边的依据是添加了field的 sort_index 字段,这个字段不需要在创建实例的时候被初始化,也不会出现在__repr__· 方法中。 使用__post__init__钩子函数为这个 sort_index 字段赋值。所以在后面的比较中,只会根据 age 的大小来比较大小。

还有两个比较方便的函数astupleasdict,它们的作用是将一个实例转换成元组和字典。

注意上面的例子中,我们是无法在外部访问到sort_index字段的。因为它没有被初始化在__init__中。 此外,可以在dataclass的装饰器内使用frozen=True参数来让类的属性都变成只读的。

另外还有一个比较有意思的设置 keyword 的方式,如下一个例子:

@dataclass
class Point:
    x: int
    _: KW_ONLY
    y: int
    z: float

p = Point(1,y=2,z=3.0)

KW_ONLY之后的字段会被认为是关键字参数, 该 feature需要 Python 版本是 3.10以上。

datetime

使用strptime时, %f 的默认行为是在右侧补0, 这个是 c 标准中的扩展 feature。一般在解析带有毫秒的情况时,需要注意右侧补零的操作。

>>> a = datetime.strptime('2022-01-02 22:01:15,6', '%Y-%m-%d %H:%M:%S,%f')
>>> a.microsecond
600000
>>> for it in a.timetuple():
...     print(it)
... 
2022   # year
1      # month
2      # day
22     # hour
1      # minute
15     # second
6      # weekday (0 = Monday)
2      # number of days since 1st January
-1     # dst - method tzinfo.dst() returned None