Python中如何优雅地初始化类?

Class A:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
A(a=1, b=2)

-----------------------分割线------------------

Class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b
data = {'a':1, 'b':2}
A(**data)

第一种方式 __init__ 方法虽然很简单,不用写那么多参数,但是真正初始化实例的时候依然要按键值对方式传入,如果有十几个,就得诶个手写传入。

第二种方式,虽然真正初始化实例时传个字典就可以了,但是 __init__方法事先给定了属性名称,如果有很多,也要诶个写进去。

有没有两者兼得的方法呢?也就是

Class A:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

但是初始化的时候,可以不用诶个传属性-值进去。

讲的可能有点乱,不知道表达清楚没有


Python中如何优雅地初始化类?

7 回复

如果真的只有少量参数, 用第二种, 简单明了, IDE 里面的提示可以很清楚的看到有哪些参数要传, 最怕的是出现这种提示: func(*args, **kwargs), 丁点儿提示都没有呀! 除了翻文档还能干啥, 忘一次翻一次;

如果有大量参数, 怕是把一些相关的参数抽象到单独的类中更好哦(现在想想 matplotlib 的 api 用起来略烦人);

还有, "传个字典就可以了"这种想法要三思, 用在复杂系统中会直接导致程序逻辑不清晰, 重构困难(有时看到满屏的字典在飞就会想: 重构? 怕是重新撸一个更轻松哦), 稳健性超低, 改一个地方可能导致 N 个地方都要改, 字典当成纯粹的数据结构用就好了, OOP 还是多抽象跟封装.


在Python里初始化类,最核心的就是 __init__ 方法。但“优雅”这事儿,得看场景。我直接上几个典型例子,你一看就懂。

1. 基础玩法:直接赋值 这是最常用的,简单直接。

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

user = User("张三", 25)

2. 进阶玩法:带默认值和类型提示 用类型提示让代码更清晰,加上默认值更灵活。

class User:
    def __init__(self, name: str, age: int = 18):
        self.name = name
        self.age = age

user1 = User("李四") # age用默认值18
user2 = User("王五", 30)

3. 高级玩法:用 dataclass (Python 3.7+) 如果类主要是存数据,用 @dataclass 最省事,自动生成 __init____repr__ 这些方法。

from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int = 18 # 同样可以给默认值

user = User("赵六", 22)
print(user) # 自动有好看的输出:User(name='赵六', age=22)

4. 工厂模式:用类方法创建 当初始化逻辑比较复杂,或者有不同创建方式时,可以用 @classmethod

class User:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    @classmethod
    def from_birth_year(cls, name: str, birth_year: int):
        from datetime import datetime
        age = datetime.now().year - birth_year
        return cls(name, age) # 注意这里返回 cls(...)

# 通过年份创建用户
user = User.from_birth_year("小明", 1995)

总结一下:

  • 普通情况用 __init__ 就行。
  • 数据类无脑上 dataclass
  • 创建逻辑复杂就用类方法工厂。

根据你的实际需求选最合适的那个。

第一种也可以传字典进去啊

第二种逻辑清晰,易于重构

没听说过大量参数还优雅一说,楼主确定是参数而不是数据?

如果你设计的类参数很多,那说明这个类设计的有问题,参考 clean architecture 前面几章。

好的 谢谢~

回到顶部