向您展示所需位置参数的效果的非常简单的示例:
>>> class Temp:
def __init__(self, **kwargs):
if kwargs:
self.temp = kwargs['temp']
>>> t = Temp()
>>> class Temp2:
def __init__(self, opt1 = None, opt2 = None):
self.opt1 = opt1
self.opt2 = opt2
>>> t2 = Temp2()
>>> class Temp3:
def __init__(self, req, opt1 = None, opt2 = None):
self.req = req
self.opt1 = opt1
self.opt2 = opt2
>>> t3 = Temp3()
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
t3 = Temp3()
TypeError: __init__() missing 1 required positional argument: 'req'
>>>
在第一类中,**kwargs 允许我实例化并传递我想要的任何关键字参数。这是一个星期的例子,但你可以对存在性进行一些初始化检查,然后对键名进行子检查。
在第二个类中,通过使用... = None,如果未提供参数,我将默认该参数。再说一遍,解释器很高兴,因为所有参数都收到了一个值!
在最后一节课中,我们看到了错误。请注意,req 未使用默认值定义。因此解释器要求它接收一个实例化它。当我不提供它时,你会得到TypeError 告诉你。
简而言之,如果没有正确实例化一个类,您将无法访问其任何属性或使用其成员函数!
编辑:想要更详细地解释它
此外,在 OOP/D 中,尝试找到避开长 __init__() 函数头的方法。试试这样的:
>>> class TM:
def __init__(self, **kwargs):
init_args = {'states': [],
'start': None,
'accept': None,
'reject': None,
'alpha': [],
'tAlpha': [],
'tape': None, # make later
'transitions': [],
'head': None}
for arg, default in init_args.items():
setattr(self, arg, kwargs.get(arg, default))
>>> tm = TM()
再次,使用**kwargs 来确定我想在初始化时为对象提供值的时间,但我默认使用预定义的列表!分解一下:
init_args 是一个现成的字典(就像kwargs。不要让** 吓到你,它只是字典unpacking operator。列表也有一个,它实际上是一个*。
for arg, default ... setattr(self, arg, kwargs.get(arg, default)) 遍历我们预定义的参数容器,然后创建一个self.[insert_arg] 属性,其值来自kwargs.get()。它会寻找arg,如果找不到,就使用我们已经拥有的default!
所以稍后当您想在 Parser 类中进行单一属性访问时:
>>> class TM:
def __init__(self, **kwargs):
init_args = {'states': [],
'start': None,
'accept': None,
'reject': None,
'alpha': [],
'tAlpha': [],
'tape': None, # make later
'transitions': [],
'head': None}
for arg, default in init_args.items():
setattr(self, arg, kwargs.get(arg, default))
>>> tm = TM()
>>> tm.states.append('it works!')
>>> tm.states
['it works!']
>>>