如果使用默认关键字参数,如何检查函数调用

时间:2017-10-04 09:47:12

标签: python default keyword-argument

我正在研究一些初始化函数/方法 如果默认值用于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的所有好处。

3 个答案:

答案 0 :(得分:3)

你能做什么:

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"提取存储在键中的值(即第一个参数)的字典的函数,如果键不存在,则回退到第二个参数,即"默认值"值。

不知道这是否会有所帮助?

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

这样你可以有两个主要优势:

  • 您的属性列表将作为参数直接添加到类中,以便您可以访问它。
  • 如果密钥存在,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

答案 1 :(得分:1)

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.
--------------------------------------------------

答案 2 :(得分:0)

我最终想出的 - 在同事的帮助下 - 使用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()填写缺失的密钥/提出警告等。

对我来说,这就是我想要的一切:

  • 明确默认值
  • 简单,不使用不明显的语言功能
  • 显式解包 - 如果仍然缺少某些内容,则会收到错误。
  • 灵活/清洁do_something()
  • 更?