如何在Python3类初始化函数中使用**kwargs?
我正在用Python3编写一个类,我希望能够从用户那里获取各种关键字参数,并存储这些值以供以后在类方法中使用。示例代码如下所示:如何在Python3类初始化函数中使用**kwargs?,python,python-3.x,oop,Python,Python 3.x,Oop,我正在用Python3编写一个类,我希望能够从用户那里获取各种关键字参数,并存储这些值以供以后在类方法中使用。示例代码如下所示: class MathematicalModel: def __init__(self, var1, var2, var3, **kwargs): self.var1 = var1 self.var2 = var2 self.var3 = var3 self.var4 = kwarg1
class MathematicalModel:
def __init__(self, var1, var2, var3, **kwargs):
self.var1 = var1
self.var2 = var2
self.var3 = var3
self.var4 = kwarg1
self.var5 = kwarg2
self.var6 = kwarg6
def calculation1(self):
x = self.var1 + self.var2 + self.var3
return x
def calculation2(self):
y = self.var1 * self.var2 * var3
return y
class MathematicalModelExtended(MathematicalModel):
def __init__(self, var1, var2, var3, **kwargs):
super.__init__(self, var1, var2, var3, **kwargs)
def calculation1(self):
'''Overrides calculation1 method from parent DoThis'''
x = (self.var1 + self.var2 + self.var3) / self.kwarg1
return x
def calculation2(self):
'''Overrides calculation2 method from parent DoThis'''
y = (self.var1 * self.var2 * self.var3) / (self.kwarg1 + self.kwarg2)
return y
a = MathematicalModel(1, 2, 3)
b = MathematicalModelExtended(1, 2, 3, var4 = 4, var5 = 5, var6 = 6)
但是,我不确定这是如何工作的,原因如下:
a) 如果用户没有为b、c、甚至a提供参数,该怎么办?然后代码将抛出一个错误,因此我不确定在这种情况下如何初始化这些属性。
b) 当我不知道用户事先传递了什么关键字参数时,如何访问与关键字关联的值
我计划在数学公式中使用变量。某些变量(不包括在kwargs
中)将在每个公式中使用,而其他变量(在kwargs
中的变量)将仅在其他公式中使用。我计划在另一个类中包装MathematicalModel
,比如soMathematicalModelExtended(MathematicalModel)
,以实现这一点
谢谢大家! 夸尔格一般思想
当您使用self.var=value
加载变量时,它会将变量添加到一个内部字典中,该字典可以通过self.\uuuu dict\uuuu
访问
class Foo1:
def __init__(self, **kwargs):
self.a = kwargs['a']
self.b = kwargs['b']
foo1 = Foo1(a=1, b=2)
print(foo1.a) # 1
print(foo1.b) # 2
print(foo1.__dict__) # {'a': 1, 'b': 2}
class Foo5:
a = 'Initial Value for A'
b = 'Initial Value for B'
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
foo5 = Foo5(a=1)
print(foo5.a) # 1
print(foo5.b) # Initial Value for B
print(foo5.__dict__) # {'a': 1}
如果要允许任意参数,可以利用kwargs
也是一个字典的事实,并使用update()
函数
class Foo2:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
foo2 = Foo2(some_random_variable=1, whatever_the_user_supplies=2)
print(foo2.some_random_variable) # 1
print(foo2.whatever_the_user_supplies) # 2
print(foo2.__dict__) # {'some_random_variable': 1, 'whatever_the_user_supplies': 2}
class Foo6:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def do_something(self):
for k, v in self.__dict__.items():
print(f"{k} -> {v}")
foo6 = Foo6(some_random_variable=1, whatever_the_user_supplies=2)
foo6.do_something()
# some_random_variable -> 1
# whatever_the_user_supplies -> 2
这将防止您在尝试存储不存在的值时出错
class Foo3:
def __init__(self, **kwargs):
self.a = kwargs['a']
self.b = kwargs['b']
foo3 = Foo3(a=1) # KeyError: 'b'
如果要确保在类中设置变量a
或b
,而不管用户提供了什么,可以创建类属性或使用kwargs.get()
但是,使用此方法,变量属于类而不是实例。这就是为什么您会看到foo5.b
返回字符串,但它不在foo5.\uu dict\uuu
中
class Foo1:
def __init__(self, **kwargs):
self.a = kwargs['a']
self.b = kwargs['b']
foo1 = Foo1(a=1, b=2)
print(foo1.a) # 1
print(foo1.b) # 2
print(foo1.__dict__) # {'a': 1, 'b': 2}
class Foo5:
a = 'Initial Value for A'
b = 'Initial Value for B'
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
foo5 = Foo5(a=1)
print(foo5.a) # 1
print(foo5.b) # Initial Value for B
print(foo5.__dict__) # {'a': 1}
如果您允许用户自由指定他们想要的任何kwargs
,您可以在函数中迭代\uuuuu dict\uuuuu
class Foo2:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
foo2 = Foo2(some_random_variable=1, whatever_the_user_supplies=2)
print(foo2.some_random_variable) # 1
print(foo2.whatever_the_user_supplies) # 2
print(foo2.__dict__) # {'some_random_variable': 1, 'whatever_the_user_supplies': 2}
class Foo6:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def do_something(self):
for k, v in self.__dict__.items():
print(f"{k} -> {v}")
foo6 = Foo6(some_random_variable=1, whatever_the_user_supplies=2)
foo6.do_something()
# some_random_variable -> 1
# whatever_the_user_supplies -> 2
但是,根据您在类中执行的其他操作,最终可能会得到比用户提供的更多的实例属性。因此,最好让用户提供一个字典作为参数
class Foo7:
def __init__(self, user_vars):
self.user_vars = user_vars
def do_something(self):
for k, v in self.user_vars.items():
print(f"{k} -> {v}")
foo7 = Foo7({'some_random_variable': 1, 'whatever_the_user_supplies': 2})
foo7.do_something()
# some_random_variable -> 1
# whatever_the_user_supplies -> 2
寻址您的代码
对于更新后的代码,我建议您使用self.\u dict\u.update(kwargs)
方法。然后,您可以在没有遇到所依赖的变量时引发错误(option1
method),也可以在未定义变量时为该变量设置默认值(option2
method)
诚然,如果MathematicalModel
永远不会使用除var1
、var2
和var3
以外的任何东西,那么传递kwargs
是没有意义的
class MathematicalModel:
def __init__(self, var1, var2, var3, **kwargs):
self.var1 = var1
self.var2 = var2
self.var3 = var3
class MathematicalModelExtended(MathematicalModel):
def __init__(self, var1, var2, var3, **kwargs):
super().__init__(var1, var2, var3)
self.__dict__.update(kwargs)
def option1(self):
# Trap error if you need var4 to be specified
if 'var4' not in self.__dict__:
raise ValueError("Please provide value for var4")
x = (self.var1 + self.var2 + self.var3) / self.var4
return x
def option2(self):
# Use .get() to provide a default value when the user does not provide it.
_var4 = self.__dict__.get('var4', 1)
x = (self.var1 + self.var2 + self.var3) / self.var4
return x
a = MathematicalModel(1, 2, 3)
b = MathematicalModelExtended(1, 2, 3, var4=4, var5=5, var6=6)
print(b.option1()) # 1.5
print(b.option2()) # 1.5
夸尔格一般思想
当您使用self.var=value
加载变量时,它会将变量添加到一个内部字典中,该字典可以通过self.\uuuu dict\uuuu
访问
class Foo1:
def __init__(self, **kwargs):
self.a = kwargs['a']
self.b = kwargs['b']
foo1 = Foo1(a=1, b=2)
print(foo1.a) # 1
print(foo1.b) # 2
print(foo1.__dict__) # {'a': 1, 'b': 2}
class Foo5:
a = 'Initial Value for A'
b = 'Initial Value for B'
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
foo5 = Foo5(a=1)
print(foo5.a) # 1
print(foo5.b) # Initial Value for B
print(foo5.__dict__) # {'a': 1}
如果要允许任意参数,可以利用kwargs
也是一个字典的事实,并使用update()
函数
class Foo2:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
foo2 = Foo2(some_random_variable=1, whatever_the_user_supplies=2)
print(foo2.some_random_variable) # 1
print(foo2.whatever_the_user_supplies) # 2
print(foo2.__dict__) # {'some_random_variable': 1, 'whatever_the_user_supplies': 2}
class Foo6:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def do_something(self):
for k, v in self.__dict__.items():
print(f"{k} -> {v}")
foo6 = Foo6(some_random_variable=1, whatever_the_user_supplies=2)
foo6.do_something()
# some_random_variable -> 1
# whatever_the_user_supplies -> 2
这将防止您在尝试存储不存在的值时出错
class Foo3:
def __init__(self, **kwargs):
self.a = kwargs['a']
self.b = kwargs['b']
foo3 = Foo3(a=1) # KeyError: 'b'
如果要确保在类中设置变量a
或b
,而不管用户提供了什么,可以创建类属性或使用kwargs.get()
但是,使用此方法,变量属于类而不是实例。这就是为什么您会看到foo5.b
返回字符串,但它不在foo5.\uu dict\uuu
中
class Foo1:
def __init__(self, **kwargs):
self.a = kwargs['a']
self.b = kwargs['b']
foo1 = Foo1(a=1, b=2)
print(foo1.a) # 1
print(foo1.b) # 2
print(foo1.__dict__) # {'a': 1, 'b': 2}
class Foo5:
a = 'Initial Value for A'
b = 'Initial Value for B'
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
foo5 = Foo5(a=1)
print(foo5.a) # 1
print(foo5.b) # Initial Value for B
print(foo5.__dict__) # {'a': 1}
如果您允许用户自由指定他们想要的任何kwargs
,您可以在函数中迭代\uuuuu dict\uuuuu
class Foo2:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
foo2 = Foo2(some_random_variable=1, whatever_the_user_supplies=2)
print(foo2.some_random_variable) # 1
print(foo2.whatever_the_user_supplies) # 2
print(foo2.__dict__) # {'some_random_variable': 1, 'whatever_the_user_supplies': 2}
class Foo6:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def do_something(self):
for k, v in self.__dict__.items():
print(f"{k} -> {v}")
foo6 = Foo6(some_random_variable=1, whatever_the_user_supplies=2)
foo6.do_something()
# some_random_variable -> 1
# whatever_the_user_supplies -> 2
但是,根据您在类中执行的其他操作,最终可能会得到比用户提供的更多的实例属性。因此,最好让用户提供一个字典作为参数
class Foo7:
def __init__(self, user_vars):
self.user_vars = user_vars
def do_something(self):
for k, v in self.user_vars.items():
print(f"{k} -> {v}")
foo7 = Foo7({'some_random_variable': 1, 'whatever_the_user_supplies': 2})
foo7.do_something()
# some_random_variable -> 1
# whatever_the_user_supplies -> 2
寻址您的代码
对于更新后的代码,我建议您使用self.\u dict\u.update(kwargs)
方法。然后,您可以在没有遇到所依赖的变量时引发错误(option1
method),也可以在未定义变量时为该变量设置默认值(option2
method)
诚然,如果MathematicalModel
永远不会使用除var1
、var2
和var3
以外的任何东西,那么传递kwargs
是没有意义的
class MathematicalModel:
def __init__(self, var1, var2, var3, **kwargs):
self.var1 = var1
self.var2 = var2
self.var3 = var3
class MathematicalModelExtended(MathematicalModel):
def __init__(self, var1, var2, var3, **kwargs):
super().__init__(var1, var2, var3)
self.__dict__.update(kwargs)
def option1(self):
# Trap error if you need var4 to be specified
if 'var4' not in self.__dict__:
raise ValueError("Please provide value for var4")
x = (self.var1 + self.var2 + self.var3) / self.var4
return x
def option2(self):
# Use .get() to provide a default value when the user does not provide it.
_var4 = self.__dict__.get('var4', 1)
x = (self.var1 + self.var2 + self.var3) / self.var4
return x
a = MathematicalModel(1, 2, 3)
b = MathematicalModelExtended(1, 2, 3, var4=4, var5=5, var6=6)
print(b.option1()) # 1.5
print(b.option2()) # 1.5
谢谢你的回复,但我不确定我是否理解。在回答的第一部分中,dict是在**kwargs作为参数传递时创建的内部字典吗?第二,我不明白,是定义类值,然后稍后重写它们,只是为了让它们有特定的名称吗?我想我对第二种方法的混淆是,为什么我要实例化可能使用或可能不使用的属性?有没有更优雅的方法来实现这一点?我的困惑是,为什么您希望允许用户定义任意的Kwarg,以及您打算如何使用它们。我可以理解,如果你只是把它们引导到你的类中调用的另一个类或函数,但我感觉不到你在做什么。因此,如果您需要确保无论用户输入什么,都可以访问某些变量,那么在类或实例中提前定义它们会有所帮助。我会使用
Foo7
方法,将用户的所有输入保存在一个变量中。然后你可以确切地看到它们提供了什么,并将其与关键函数隔离开来“我可以理解,如果你只是将它们引导到类中调用的另一个类或函数中,但我感觉不到这就是你正在做的事情”实际上,这就是我计划要做的。用户将提供数学公式中特定变量的数字(但并非所有实例中的所有公式都需要)