0%

python snippet

Principle

SOLID

  • S (单一职责原则 Single responsibility principle)

    • 一个类应该仅仅只有一个被修改的理由。
  • O (开放-关闭原则 Open–closed principle)

    • 类应该对扩展开放,对修改封闭。
  • L (里氏替换原则 Liskov Substitution Principle)

    • 子类应该可以随意替换它的父类 ,而不破坏程序 本身的功能
  • I (接口隔离原则 Interface Segregation Principles)

    • 客户(client)应该不依赖于它不使用的方法
  • D (依赖倒置原则 Dependency Inversion Principle)

    • 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。

idea

  • 好代码在处理边界情况时应该是简洁的、“润物细无声”的

code practise

边界情况(Edge cases)

  • bad style:
    • LBYL(Look Before You Leap)
  • better style:
    • EAFP(Easier to Ask for Forgiveness than Permission)
  • best style
    • 在日常编码时,我们应该尽量避免去手动校验数据。而是应该使用(或者自己实现)合适的第三方校验模块,把这部分边界处理工作抽象出去,简化主流程代码。

Method

统计运行时间

1
2
3
4
# 毫秒值
start_time = time.perf_counter()
xxx
cost_time = int((time.perf_counter() - start_time)* 1000)

__call__函数

__call__ 方法是 Python 中的一个特殊方法(也称为魔术方法),用于将一个对象作为函数调用。当一个对象被作为函数调用时,Python 解释器会自动调用该对象的 __call__ 方法。

在类中定义 __call__ 方法可以使对象具有可调用的行为,就像调用函数一样。这样的对象被称为可调用对象。通过实现 __call__ 方法,我们可以在对象被调用时执行特定的逻辑。

以下是一个示例,展示了如何定义和使用 __call__ 方法:

1
2
3
4
5
6
class CallableClass:
def __call__(self, *args, **kwargs):
print("Object is being called")

obj = CallableClass()
obj() # 等同于调用 obj.__call__()

在上面的示例中,我们定义了一个名为 CallableClass 的类,并在其中实现了 __call__ 方法。当创建 CallableClass 的实例 obj 并将其作为函数调用时,__call__ 方法会被自动调用,并打印出 “Object is being called”。

需要注意的是,__call__ 方法可以带有参数,就像普通的函数一样。我们可以在 __call__ 方法中定义任意的逻辑,可以访问实例的属性、调用其他方法等。

使用 __call__ 方法可以使对象具有类似函数的行为,这在某些情况下非常有用,例如实现可调用的类或实现函数式编程的概念。

**使用

  • ** 运算符用于解包字典或关键字参数。当应用于字典时,** 运算符可以将字典中的键值对解包为一系列关键字参数传递给函数或方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def print_person_info(name, age, city):
    print(f"Name: {name}")
    print(f"Age: {age}")
    print(f"City: {city}")

    person = {
    'name': 'Alice',
    'age': 25,
    'city': 'New York'
    }

    print_person_info(**person)

布尔真假判断

虽然所有用户类实例的布尔值都是真。但是 Python 提供了改变这个行为的办法:自定义类的 __bool__ 魔法方法 (在 Python 2.X 版本中为 __nonzero__。当类定义了 __bool__ 方法后,它的返回值将会被当作类实例的布尔值。

另外,__bool__ 不是影响实例布尔真假的唯一方法。如果类没有定义 __bool__ 方法,Python 还会尝试调用 __len__ 方法(也就是对任何序列对象调用 len 函数),通过结果是否为 0 判断实例真假。

在条件判断中使用 all() / any()

all()any() 两个函数非常适合在条件判断中使用。这两个函数接受一个可迭代对象,返回一个布尔值,其中:

  • all(seq):仅当 seq 中所有对象都为布尔真时返回 True,否则返回 False
  • any(seq):只要 seq 中任何一个对象为布尔真就返回 True,否则返回 False

使用 partial 构造新函数

1
2
3
4
5
def multiply(x, y):
return x * y
def double(value):
# 返回另一个函数调用结果
return multiply(2, value)

可写成

1
2
3
import functools

double = functools.partial(multiply, 2)

Mixin

Mixin 是面向对象编程中的一个术语,它表示一种设计模式,用于将一组功能或行为以模块化的方式添加到类中,而不需要使用继承的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class SendMailMixin:
def send_mail(self, email):
print(f"Sending mail to {email}")

class User:
def __init__(self, email):
self.email = email

class AdminUser(User, SendMailMixin):
def send_admin_mail(self):
self.send_mail(self.email)

admin = AdminUser("admin@example.com")
admin.send_admin_mail() # 输出: Sending mail to admin@example.com

Mixin和abc.ABC的区别:

  1. 用途: Mixin侧重于代码复用和功能扩展,而abc.ABC则用于定义抽象类和接口。
  2. 继承关系: Mixin通常与其他类一起使用多重继承,而abc.ABC作为基类被具体类继承。
  3. 抽象程度: Mixin可以包含具体的实现,而abc.ABC中的抽象方法必须由子类实现。
  4. 类型检查: abc.ABC可用于类型检查,而Mixin无法直接进行类型检查。

LOOP

1
2
for i, name in enumerate(names):
print(i, name)
  • 使用 product 扁平化多层嵌套循环
  • 使用 islice 实现循环内隔行处理
  • 使用 takewhile 替代 break 语句
  • 使用生成器编写自己的修饰函数

修改外层变量时记得使用 nonlocal

  • 闭包的参数使用

类对象

  • cls
1
2
@classmethod
def _send_request(cls, method, endpoint, json=None, params=None):

使用 dataclass 简化代码

总结一下,dataclass主要提供了以下几方面的功能:

  1. 自动生成构造函数和基本方法

    • 自动生成__init__构造函数
    • 自动生成__repr____eq__等基本方法
  2. 数据字段管理

    • 定义数据字段
    • 支持为字段设置默认值
    • 支持字段类型注解
    • 支持只读字段、后期初始化字段
  3. 数据类行为定制

    • 可自定义字段排序
    • 可自定义字段命名规则(snake_case/CamelCase)
    • 支持自定义__post_init__方法做数据校验
    • 可控制是否生成__repr__方法
    • 支持生成__hash__方法用于哈希
  4. 性能优化

    • 支持使用__slots__优化内存使用
  5. 与静态类型检查工具结合

    • 支持与mypy等类型检查工具结合使用
  6. 继承和嵌套

    • 支持数据类的继承
    • 支持嵌套数据类作为字段

通过这些功能,dataclass可以极大简化数据类的定义和使用,减少样板代码。它使得创建数据类变得高效和优雅,同时还提供了足够的定制空间。无论是简单的数据持有对象还是复杂的数据结构,dataclass都能发挥它的优势,提高代码的可读性和可维护性。

Package

文件处理

  • pathlib

Grammar

  • *args 接收并处理所有传递进来的位置参数,**kwargs 接收并处理所有传递进来的关键字参数。