我有下面这样的类:
class DecisionTreeRegressor():
def __init__(self, min_leaf=5, impurity_threshold=1e-5,
root=None, leaf_value=None, impurity=None):
self.min_leaf = min_leaf
self.impurity_threshold = impurity_threshold
self.root = root
self._leaf_calculation = leaf_value
self._impurity_calculation = impurity
我想在另一个名为DecisionTreeRegressor
的类中初始化RandomForestRegressor
类,该类本身及其父类RandomForest
具有以下结构:
class RandomForest():
def __init__(self, n_estimators=10, min_leaf=5,
sample_size = 2/3, min_impurity=1e-5):
self.n_estimators = n_estimators
self.min_leaf = min_leaf
self.sample_size = sample_size
self.min_impurity = min_impurity
class RandomForestRegressor(RandomForest):
def __init__(self):
super().__init__()
self.tree = DecisionTreeRegressor
self.trees = [self.tree(min_leaf=self.min_leaf)
for i in range(self.n_estimators)]
这将返回以下错误消息:
TypeError: __init__() got an unexpected keyword argument 'min_leaf'
我之所以感到困惑,原因如下:
DecisionTreeRegressor(min_leaf=5)
工作正常。
此外,如果我将RandomForestRegressor
更改为:
class RandomForestRegressor(RandomForest):
def __init__(self):
super().__init__()
self.tree = DecisionTreeRegressor
self.trees = [self.tree() for i in range(self.n_estimators)]
这也可以正常工作,self.trees
是一个由DecisionTreeRegressor
类的n个不同实例填充的列表。
为什么要传递min_leaf
自变量来调用错误消息呢?
答案 0 :(得分:1)
我假设您是在打电话:
RandomForestRegressor(min_leaf=5)
RandomForestRegressor
类的初始化程序没有声明的关键字参数,根本不需要任何参数。
您需要显式地将它们添加到签名中,或将kwargs添加到签名中。
class RandomForestRegressor(RandomForest):
def __init__(self, **kwargs):
super().__init__(**kwargs)
答案 1 :(得分:1)
方法或函数(方法类的实例)可以定义参数。但是,调用该方法时,只能接受其定义的参数。例如:
def functionwithnoparameters():
pass
下面的代码将起作用。
functionwithnoparameters()
但是,下面的代码将引发TypeError,因为该函数不需要任何参数。
functionwithnoparameters(1)
为其提供了太多参数,超出了预期,因此引发TypeError。您被误认为只有过多或过少的value参数才能引发TypeError。但是,根据此示例,过多或太少的关键字参数也会导致TypeError。
functionwithnoparameters(one=1)
但是,DecisionTreeRegressor没有定义任何关键字参数,因此当给出一个参数时,它会咳嗽TypeError。这就是TypeError的原因。
您的问题有两种解决方案。
1)解释器认为min_leaf和其他参数是值参数,而不是关键字参数。因为min_leaf是第一个参数,所以您可以只使用min_leaf的值!
2)更清洁的解决方案。 Python中的参数默认为值参数,并且当参数以*(所有其他值参数的元组)开头时,会标记值参数的结尾。如果要标记值参数的末尾而无需启用无限值参数,请使用*作为普通参数。当值参数结束时,关键字参数开始。如果参数以**开头,则会占用无限的关键字参数。这必须是方法的最后一个参数。
现在,根据第二种解决方案来重写DecisionTreeRegressor类:
class DecisionTreeRegressor():
def __init__(self, *, min_leaf=5, impurity_threshold=1e-5, root=None, leaf_value=None, impurity=None):
self.min_leaf = min_leaf
self.impurity_threshold = impurity_threshold
self.root = root
self._leaf_calculation = leaf_value
self._impurity_calculation = impurity
关键字参数前面的小*可以完全解决问题。第一个解决方案只是创可贴解决方案。
我对杰夫·梅卡多(Jeff Mercado)的回答感到不满意,因为TypeError的出现是由于缺少植根于DecisionTreeRegressor类的支持,而不是由于RandomForestRegressor类的构造函数中缺少参数。
但是,我强烈建议RandomForestRegressor的构造函数应采用RandomForest的参数,并使用这些参数(而不是其默认参数)调用RandomForest的构造函数。既然我告诉了您如何实现这两种方法,那么无论您想要使用什么,它们都可以是值或关键字参数。