使用继承从__init__减少样板

时间:2019-02-05 05:05:43

标签: python python-internals

我正在尝试通过超类注入构造函数,即__init__,以避免在我所有域类的__init__中产生样板代码。

例如:

class Structure:
    _fields = []

    def __init__(self, *args):
        if len(args) != len(self._fields):
            raise TypeError("Wrong # arguments")
        for name, value in zip(self._fields, args):
            setattr(self, name, value)

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

stock = Stock("Amzn", "11", "2100")
print(stock.name)

当构造函数限制为*args时,以上代码可以正常工作。但是有些域类也需要**kwargs

例如以下内容:

class Structure:
    _fields = []

    def __init__(self, *args, **kwargs):
        if (len(args) + len(kwargs)) != len(self._fields):
            raise TypeError("Wrong # arguments")

        for name, value in zip(self._fields, args):
            setattr(self, name, value)

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

stock = Stock("Amzn", "11", price = "2100")
stock.price #AttributeError, stock object has no attribute 'price'

但是显然上面的代码不会设置kwarg,因为我从未接触过__init__中的kwarg。知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

如何检查kwargs是否存在?

>>> class SC: 
...:     _fields = [] 
...:     def __init__(self, *args, **kwargs):
...:         if (len(args) + len(kwargs)) != len(self._fields):
...:              raise TypeError("Wrong # arguments") 
...:         for name, value in zip(self._fields, args): 
...:             setattr(self, name, value) 
...:         if kwargs: 
...:             self.__dict__.update(kwargs) 
...:                                                                                                                                                                                      

>>> class SD2(SC): 
...     _fields = ['name', 'shares', 'price'] 


>>> i = SD2(name='Amzn', shares=1, price=2)                                                                                                                                              
>>> i.name                                                                                                                                                                               
'Amzn'
>>> i.shares  
1

这也是如此:

>>>u= SD2('Amzn', shares=1, price=2)                                                                                                                                                             
>>>u.name                                                                                                                                                                                
'Amzn'