如何使用默认关键字参数在函数调用中检查
我正在开发一些初始化函数/方法,如果默认值用于kwargs,它应该会发出警告 。我不能 找出如何做到这一点,谷歌也没有帮助我。 任何解决方案?如何使用默认关键字参数在函数调用中检查
为了说明
class MyClass():
def __init__(a=0,b=1):
''' Should warn you if using default.'''
self._a = a
self._b = b
应该采取行动如下
MyClass(a=1)
>>> 'warning: default b=1 is used.
一个为什么要警告:Defualts有没有说明使用的典型值。但是最终用户应该设置它们而不是懒惰(!)。最终用户使用kwargs操纵yamls:如果他/她弄糟了,让最终用户意识到。基本上我需要args的(软)要求以及kwargs的所有好处。
使用kwargs
在__init__
的警告,然后一个专用initialize
函数变量的赋值:
class MyClass():
def __init__(self, **kwargs):
defaults = dict(a=0, b=1)
for key,val in defaults.items():
if key not in kwargs:
print("warning: default {}={} is used.".format(key, val))
kwargs[key]=val
self.initialize(**kwargs)
def initialize(self, a=0, b=1):
self._a = a
self._b = b
MyClass()
print('-'*50)
MyClass(a=5)
print('-'*50)
MyClass(a=4,b=3)
输出是:
warning: default b=1 is used.
warning: default a=0 is used.
--------------------------------------------------
warning: default b=1 is used.
--------------------------------------------------
谢谢!这听起来像一个很好的一般方法。有点冗长的默认值的双重定义,但这是你在语言中可能无法做到的事情。 – balletpiraat
你可以做什么:
class MyClass(object):
def __init__(self, **kwargs):
if not 'b' in kwargs:
print "warning"
self._a = kwargs.get('a', 0)
self._b = kwargs.get('b', 1)
该代码使用提取存储在该键的值的字典的“获取”功能(即第一个参数),如果该键不存在,第二个参数是“默认”值的后备。
不知道这是否有一些帮助?
Python 2.7 "get" function for a dictionary
更新
因为从库恩的答案是非常有趣的,我想进一步推:
class MyClass(object):
def __init__(self, **kwargs):
defaults = dict(a=0, b=1)
for key, value in defaults.iteritems():
if not key in kwargs:
print "Warning: default {0}={1} is used.".format(key, value)
kwargs.setdefault(key, value)
self.__dict__.update(kwargs)
m = MyClass()
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
m = MyClass(a=10)
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
m = MyClass(a=10, b=11)
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
这种方式,您可以有两个主要的优点:
- 您的属性列表将直接添加到类中作为参数,以便您可以访问它。
-
setdefault
方法提取值,如果密钥存在,并且如果不是简单地添加具有指定的默认值的密钥。
据我所知,这个代码可以是在非受控环境非常危险,所以你最终可以为您的类更复杂的结构回退,使用方法:
-
__getattr__(self, attributename)
为根据定义的名称提取属性值,以便您可以将所有值保存在本地变量(如self.classparameters或 -
__setattr__(self, attributename, attributevalue)
)中以设置值。
这是代码:
class MyClass(object):
def __init__(self, **kwargs):
defaults = dict(a=0, b=1)
for key, value in defaults.iteritems():
if not key in kwargs:
print "Warning: default {0}={1} is used.".format(key, value)
kwargs.setdefault(key, value)
self.__dict__.update(kwargs)
def __getattr__(self, parameter):
return self.__dict__.get(parameter)
def __setattr__(self, parameter, value):
self.__dict__.update({parameter: value})
m = MyClass()
m.b = 11
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
m = MyClass(a=10)
m.b = 101
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
m = MyClass(a=10, b=11)
m.b = 1001
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
这是一件需要非常小心地手持,因为你可以(而且会)在多个场合一些严重的问题。
警告:这是不如何使用
__setattr__
和__getattr__
的解释,反而是接近与多种解决方案相同的问题一个简单的(和愚蠢)的方式,因此,如果你知道如何改进此位用更智能的方式使用那些魔术方法,不客气。
实施这一过程的另一种方式,这可能是更冗长,但可让您有发生什么控制的大量使用装饰@property:
class MyClass(object):
def __init__(self, **kwargs):
self.classparam = dict(a=0, b=1)
for key, value in self.classparam.iteritems():
if not key in kwargs:
print "Warning: default {0}={1} is used.".format(key, value)
kwargs.setdefault(key, value)
self.classparam.update(kwargs)
@property
def a(self):
return self.classparam.get('a')
@a.setter
def a(self, value):
self.classparam.update(a=value)
@property
def b(self):
return self.classparam.get('b')
@b.setter
def b(self, value):
self.classparam.update(b=value)
m = MyClass()
m.b = 10
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
m = MyClass(a=10)
m.b = 100
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
m = MyClass(a=10, b=11)
m.b = 1000
print "a: {0}; b: {1}".format(m.a, m.b)
print "-"*30
我喜欢这个解决方案!这非常重要。对于少数几个kwargs会很好。 ThomasKühn的答案将用于更一般的情况。 – balletpiraat
谢谢你提出另一个鼓舞人心的建议。我以前不知道setdefault方法!看到我的答案,我最终想出了什么。 – balletpiraat
@balletpiraat,不客气!其实你启发我的一些改进,我的工作流程中的参数检查:) –
我终于想出了 - 与同事的帮助 - 就是使用一个类属性来存储默认值:
举例说明:
class MySpecialClass():
default_kwargs = dict(a=0,b=0)
def __init__(self,kwargs):
_kwargs = do_something(kwargs,self.default_kwargs)
self.a = _kwargs['a']
... some more unpacking ...
instance = MySpecialClass({'a':0})
>>> some effect
其中do_something()
填补丢失的钥匙/引发警告等
对我来说,这所有我想要的:
- 明确有关默认值
- 简单,不使用未明显语言特征
- 明确拆包 - 如果还是缺少些什么,你得到一个错误。
- 灵活/清洁通过
do_something()
- 更多?
mmh ..你仍然可以使用'** kwargs',因为你使用它的方式并不明显,但总是需要一个参数传递给构造函数。使用'** kwargs'会发生什么情况是让构造函数(或任何其他函数或方法)将参数传递为'MyClass(a = 12,b ='asd')'这可能是一种更为pythonic的方式一个更全面的方式来处理一个对象。 –
你能解释为什么你需要警告有关违约?如果它们是默认值,我认为该函数应该正常运行而不会发出警告。 – noel
如果有人呼叫'MyClass(0,1)',是否应该有警告? –
那么..用户意识总是一件好事,如果用户知道如果没有特别定义,使用特定的默认值看起来非常有趣。 这也可以用于第二个值如果没有指定,基于第一个参数值改变的情况.. –