如果使用默认关键字参数,如何检查函数调用
How to check at function call if default keyword arguments are used
我正在做一些初始化工作 function/method 这应该
如果默认值用于 kwargs,警告你。我不能
弄清楚该怎么做,google 也没有帮助我。
有什么解决办法吗?
举例说明
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.
为什么要警告:默认值用于说明所使用的典型值。但是最终用户应该设置它们而不是懒惰(!)。最终用户使用 kwargs 操作 yamls:如果 he/she 搞砸了,让最终用户知道。基本上我想要 args 的(软)要求和 kwargs 的所有好处。
你可以做什么:
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)
此代码使用字典的 "get" 函数提取存储在键(即第一个参数)中的值,如果键不存在,则回退到第二个参数,即"default" 值。
不知道这是否有帮助?
Python 2.7 "get" function for a dictionary
更新
因为 Thomas Kuhn 的回答非常有趣,我想更进一步:
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
这种方式有两个主要优势:
- 您的属性列表将作为参数直接添加到 class 中,以便您可以访问它。
- 如果键存在,
setdefault
方法提取值,如果不存在,则简单地添加具有指定默认值的键。
我知道这段代码在不受控制的环境中可能非常危险,因此您最终可以使用以下方法为您的 class 回退到更复杂的结构:
__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
这需要非常小心地手持,因为在多种情况下您可能(并且将会)遇到一些严重的问题。
Alert: this is not an explanation on how to use __setattr__
and __getattr__
, instead is a simple (and stupid) way to approach the same problem with multiple solutions, so if you know how to improve this bit with a more smart way of using those magic methods, you're welcome.
实现这个过程的另一种方法,可能会更冗长,但可以让你对发生的事情有很多控制是使用装饰器@属性:
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
在 __init__
中使用 kwargs
作为警告,然后使用专用的 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.
--------------------------------------------------
在一位同事的帮助下,我最终想到的是使用 class 属性来存储默认值:
举例说明:
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()
填写缺失的 keys/raises 警告等
对我来说,这就是我想要的:
- 关于默认值的明确说明
- 简单,不使用不明显的语言特征
- 显式解包 -- 如果仍然缺少某些内容,则会出现错误。
- flexible/clean 通过
do_something()
- 更多?
我正在做一些初始化工作 function/method 这应该 如果默认值用于 kwargs,警告你。我不能 弄清楚该怎么做,google 也没有帮助我。 有什么解决办法吗?
举例说明
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.
为什么要警告:默认值用于说明所使用的典型值。但是最终用户应该设置它们而不是懒惰(!)。最终用户使用 kwargs 操作 yamls:如果 he/she 搞砸了,让最终用户知道。基本上我想要 args 的(软)要求和 kwargs 的所有好处。
你可以做什么:
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)
此代码使用字典的 "get" 函数提取存储在键(即第一个参数)中的值,如果键不存在,则回退到第二个参数,即"default" 值。
不知道这是否有帮助?
Python 2.7 "get" function for a dictionary
更新
因为 Thomas Kuhn 的回答非常有趣,我想更进一步:
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
这种方式有两个主要优势:
- 您的属性列表将作为参数直接添加到 class 中,以便您可以访问它。
- 如果键存在,
setdefault
方法提取值,如果不存在,则简单地添加具有指定默认值的键。
我知道这段代码在不受控制的环境中可能非常危险,因此您最终可以使用以下方法为您的 class 回退到更复杂的结构:
__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
这需要非常小心地手持,因为在多种情况下您可能(并且将会)遇到一些严重的问题。
Alert: this is not an explanation on how to use
__setattr__
and__getattr__
, instead is a simple (and stupid) way to approach the same problem with multiple solutions, so if you know how to improve this bit with a more smart way of using those magic methods, you're welcome.
实现这个过程的另一种方法,可能会更冗长,但可以让你对发生的事情有很多控制是使用装饰器@属性:
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
在 __init__
中使用 kwargs
作为警告,然后使用专用的 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.
--------------------------------------------------
在一位同事的帮助下,我最终想到的是使用 class 属性来存储默认值:
举例说明:
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()
填写缺失的 keys/raises 警告等
对我来说,这就是我想要的:
- 关于默认值的明确说明
- 简单,不使用不明显的语言特征
- 显式解包 -- 如果仍然缺少某些内容,则会出现错误。
- flexible/clean 通过
do_something()
- 更多?