如何自动将__init__参数分配给属性?

18 投票
5 回答
20411 浏览
提问于 2025-04-16 12:06

有没有办法自动把__init__方法的一些参数绑定到self上呢?

比如说,我们有:

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

能不能创建一个lazy_init装饰器,让我们可以用这种方式来做呢?

class Person:
    @lazy_init
    def __init__(self, name, age, address):
        ...

有没有类似的技巧?或者说,有什么好的理由不这样尝试吗?

5 个回答

4

你可以使用Python 3.7引入的数据类,像这样:

from dataclasses import dataclass

@dataclass
class MyClass:
    var_1: str
    var_2: float

或者你也可以使用fastcore库里的store_attr()方法,像这样:

from fastcore.utils import store_attr

class MyClass:
    def __init__(self, var_1, var_2):
        store_attr()

这两种方法最终都会得到相同的初始化方法:

def __init__(self, var_1, var_2):
    self.var_1 = var_1
    self.var_2 = var_2
7

这绝对是可能的,这里有一个比较简单的实现方法:

from functools import wraps

def lazy_init(init):
    import inspect
    arg_names = inspect.getargspec(init)[0]

    @wraps(init)
    def new_init(self, *args):
        for name, value in zip(arg_names[1:], args):
            setattr(self, name, value)
        init(self, *args)

    return new_init

class Person:
    @lazy_init
    def __init__(self, name, age):
        pass

p = Person("Derp", 13)
print p.name, p.age

不过,一旦你开始使用除了属性以外的东西来映射到属性上,你就会遇到一些麻烦。你至少需要一种方法来指定哪些参数要初始化为属性……到那时,这样做就会变得麻烦,可能不值得。

9

为了方便将来遇到这个问题的朋友们(Python 3.7 或更高版本):有一个叫做 dataclass 的装饰器,它正好可以做到这一点。

示例

from dataclasses import dataclass

@dataclass
class Person:
    name
    age
    address

# other methods...

撰写回答