【问题标题】:Reduce boilerplate from __init__ using Inheritance使用继承减少 __init__ 的样板文件
【发布时间】:2019-02-05 05:05:42
【问题描述】:

我正在尝试通过超类注入构造函数,即__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'

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

【问题讨论】:

  • 类似单行构造函数的东西可能是您正在寻找的东西?见本网页底部:book.pythontips.com/en/latest/one_liners.html
  • 如果是我负责的任何事情,我可能会把我的显示器扔给编写该代码的人;)当然,它可能会节省一点样板文件,但由于它不是标准约定,你如果您想依赖 Python 的工具,将会遇到各种问题。例如,您尝试执行的操作会使 help() 完全无用。您不能分配类型提示(如果您选择这样做)。等等等等
  • @DemianBrecht,而您的评论有一定的意义。我见过一些使用类似技巧在运行时定义类和类型的代码。当然,在 Python 中还有其他方法可以做到这一点,但在所有这些情况下,您都不需要帮助和“标准”工具。
  • 特别是在您编写框架或库时。你也可以在 Django、Flask 等中发现这样的事情。

标签: python python-internals


【解决方案1】:

如何检查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'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    相关资源
    最近更新 更多