欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

简化数据结构的初始化

程序员文章站 2022-07-14 18:59:52
...

有时候,我们会厌倦为无数的class编写__init__函数,而__init__函数的作用仅是为了初始化一些属性。
我们可以编写一个父类来约定子类的__init__方式,根据类属性列表来一一初始化。

class Structure:
    _fields = []
    def __init__(self, *args):
        if len(args) != len(self._fields):
            raise TypeError('Expected {} arguments'.format(len(self._fields)))
        
        # Set the arguments
        for key, value in zip(self._fields, args):
            setattr(self, key, value)


class Stock(Structure):
    _fields = ['name', 'shares', 'price']


class Point(Structure):
    _fields = ['x', 'y']


class Circle(Structure):
    _fields = ['radius']

    def area(self):
        return math.pi * self.radius ** 2


>>> s = Stock('ACME', 50, 91.1) 
>>> p = Point(2, 3)
>>> c = Circle(4.5)
>>> s2 = Stock('ACME', 50) 
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "structure.py", line 6, in __init__
    raise TypeError('Expected {} arguments'.format(len(self._fields))) 
TypeError: Expected 3 arguments

如果要支持关键字参数的初始化形式,则需要做如下更改:

class Structure:
    _fields = []
    def __init__(self, *args, **kwargs):
        if len(args) > len(self._fields):
            raise TypeError('Expected {} arguments'.format(len(self._fields)))
        
        # Set the arguments
        for key, value in zip(self._fields, args):
            setattr(self, key, value)

        # Set the remaining keyword arguments
        for name in self._fields[len(args):]:
            setattr(self, name, kwargs.pop(name))

        # Check for any remaining unknown arguments
        if kwargs:
            raise TypeError('Invalid argument(s): {}'.format(','.join(kwargs)))


class Stock(Structure):
    _fields = ['name', 'shares', 'price']

s1 = Stock('ACME', 50, 91.1)
s2 = Stock('ACME', 50, price=91.1)
s3 = Stock('ACME', shares=50, price=91.1)