栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在继承时避免长的构造函数而不隐藏构造函数,可选参数或功能

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在继承时避免长的构造函数而不隐藏构造函数,可选参数或功能

基本思想是编写

__init__
为您生成该方法的代码,其中使用显式指定的所有参数,而不是通过
*args
和/或
**kwargs
,并且甚至无需在所有这些
self.arg1= arg1
行中重复进行操作。

并且,理想情况下,它可以使添加PyCharm可用于弹出提示和/或静态类型检查的类型注释变得容易。1个

而且,当您使用它时,为什么不构建一个

__repr__
显示相同值的?甚至可能还有
__eq__
,和
__hash__
,以及字典比较操作符,以及往返于的转换,
dict
其键与每个JSON持久性的属性相匹配,并且…

或者,甚至更好的是,使用可以为您解决这些问题的库。

Python
3.7附带了这样的库

dataclasses
。或者,您可以使用第三方库(例如)
attrs
,该库可与Python
3.4和2.7(但有一定限制)一起使用。或者,对于简单的情况(对象是不可变的,并且您希望它们按照指定的顺序像其属性的元组一样工作),可以使用
namedtuple
,其适用于3.0和2.6。

不幸的是,

dataclasses
它不适用于您的用例。如果您只是这样写:

from dataclasses import dataclass@dataclassclass Parent:    arg1: str    opt_arg1: str = 'opt_arg1_default_val'    opt_arg2: str = 'opt_arg2_default_val'    opt_arg3: str = 'opt_arg3_default_val'    opt_arg4: str = 'opt_arg4_default_val'@dataclassclass Child(Parent):    arg2: str

…你会得到一个错误,因为它试图强制参数将

arg2
默认值参数后
opt_arg1
通过
opt_arg4

dataclasses
没有任何方法可以对参数(
Child(arg1, arg2,opt_arg1=…
)进行重新排序,也不能使其强制为仅关键字的参数(
Child(*, arg1, opt_arg1=…,arg2)
)。
attrs
没有开箱即用的功能,但是您可以添加它。

因此,它并不像您希望的那么琐碎,但却是可行的。


但是,如果您想自己编写此代码,您将如何

__init__
动态创建函数?

最简单的选择是

exec

您可能听说过这

exec
很危险。但这只是危险,如果您要传递来自用户的值。在这里,您只传递来自您自己的源代码的值。

它仍然很丑陋,但有时仍然是最好的答案。标准库

namedtuple
曾经是一个巨大的
exec
模板。,甚至当前版本都
exec
用于大多数方法,确实如此
dataclasses

另外,请注意,所有这些模块都将字段集存储在私有类属性中的某个位置,因此子类可以轻松读取父类的字段。如果您不这样做,则可以使用该

inspect
模块获取
Signature
基类(或用于多重继承的基类)的初始化程序,然后从那里开始。但是,
base._fields
显然使用起来要简单得多(并允许存储通常不在签名中包含的额外元数据)。

这里是一个死的简单实现不处理大部分的功能

attrs
dataclasses
,但不会为了所有自选前所有必须的参数。

def makeinit(cls):    fields = ()    optfields = {}    for base in cls.mro():        fields = getattr(base, '_fields', ()) + fields        optfields = {**getattr(base, '_optfields', {}), **optfields}    optparams = [f"{name} = {val!r}" for name, val in optfields.items()]    paramstr = ', '.join(['self', *fields, *optparams])    assignstr = "n    ".join(f"self.{name} = {name}" for name in [*fields, *optfields])    exec(f'def __init__({paramstr}):n    {assignstr}ncls.__init__ = __init__')    return cls@makeinitclass Parent:    _fields = ('arg1',)    _optfields = {'opt_arg1': 'opt_arg1_default_val',       'opt_arg2': 'opt_arg2_default_val',       'opt_arg3': 'opt_arg3_default_val',       'opt_arg4': 'opt_arg4_default_val'}@makeinitclass Child(Parent):    _fields = ('arg2',)

现在,你已经得到了完全

__init__
你想上的方法
Parent
Child
,完全可检查2(含
help
),而不必重复自己。


1.我不使用PyCharm,但是我知道在3.7发行之前,他们的开发人员已经参与了讨论,

@dataclass
并且已经在为IDE添加对它的显式支持,因此它甚至不必评估类定义以获取所有这些信息。我不知道它是否在当前版本中可用,但是如果没有,我认为它将可用。同时,
@dataclass
已经可以通过IPython自动完成功能,emacs
flycheck等对我有效,这对我来说已经足够了。:)

2.…至少在运行时。PyCharm可能无法静态地很好地解决问题,无法完成弹出窗口。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/517158.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号