【问题标题】:Is it possible get a dictionary of passed in parameters similar to kwargs(python)?是否可以获得类似于 kwargs(python) 的传入参数字典?
【发布时间】:2012-12-27 16:11:42
【问题描述】:

我目前正在创建这样的对象:

class Obj(object):
    def __init__(self,**kwargs):
        params = ['val1','val2','val3','val4',...]
        for p in params:
            setattr(self,p,kwargs.get(p,None))

我正在这样做,所以我不必这样做:

class Obj(object):
    def __init__(self,val1=None,val2=None,val3=None,val4=None,...):
        self.val1=val1
        self.val2=val2
        self.val3=val3
        self.val4=val4
        ...

我的问题是,您可以将两者混合使用吗?我可以在哪里定义预期的参数,但仍然循环参数来设置属性?我喜欢定义预期参数的想法,因为它是自我记录的,其他开发人员不必搜索使用了哪些 kwarg。

我知道这看起来很琐碎,但我正在从一些 XML 创建一个对象,因此我将传递许多参数,它只会使代码混乱并让我感到困惑。

我用谷歌搜索了这个但找不到任何东西,可能是因为字典和 kwargs 一起指向 kwarg 示例。

更新:更具体地说,是否可以获取传入参数的字典,以便 我根本不必使用 kwargs

须藤代码:

class Obj(object):
    def __init__(self,val1=None,val2=None,val3=None,val4=None,...):
        for k,v in dictionary_of_paramters.iteritems():
            setattr(self,k,v)

【问题讨论】:

    标签: python python-2.7


    【解决方案1】:

    您可以使用inspect 模块:

    import inspect
    
    def myargs(val1, val2, val3=None, val4=5):
            print inspect.currentframe().f_locals
    

    它显示了当前堆栈帧上所有可用的局部变量。

    myargs('a','b')
    ==>  {'val3': None, 'val2': 'b', 'val1': 'a', 'val4': 5}
    

    (注意:不保证在所有 Python 解释器上都实现)

    编辑:我同意这不是一个很好的解决方案。我会做的更像是:

    def _yourargs(*names):
            "returns a dict with your named local vars"
            alllocs = inspect.stack()[1][0].f_locals
            return {n:alllocs[n] for n in names}
    
    def askformine(val1, val2, val3=None, val4=5):
            "example to show just those args i'm interested in"
            print _yourargs('val1','val2','val3','val4')
    
    class Obj(object):
            "example inserting some named args as instance attributes"
            def __init__(self, arg1, arg2=4):
                     self.__dict__.update(_yourargs('arg1','arg2'))
    

    edit2稍微好一点:

    def pickdict(d,*names):
        "picks some values from a dict"
        return {n:d[n] for n in names}
    
    class Obj(object):
        "example inserting some named args as instance attributes"
        def __init__(self, arg1, arg2=4):
            self.__dict__.update(pickdict(locals(),'arg1','arg2'))
    

    【讨论】:

    • 谢谢!这就是我要找的。据我了解,它应该适用于所有纯 python 解释器,而不是像 jython 之类的东西......对吗?
    • 呃,你确定这值得吗?请记住,f_locals 将不仅仅是参数,这将使您的代码变得奇怪而神奇。只需拼出你需要的论据。
    • 奇怪而神奇……你可以封装在一个函数中来隐藏丑陋。不仅仅是参数:您可以使用您感兴趣的 var 名称列表调用您的实用程序函数。值得吗?我不这么认为。
    • @rjbez:同样的事情......我完全忘记了locals()。表明我对此有多么不喜欢:-)
    • @NedBatchelder 好的,谢谢,你们说服了我这是不值得的。
    【解决方案2】:

    没有很好的方法来获取函数所有参数的字典。 **kwargs 语法只收集额外的关键字参数,而不是那些与函数定义中的显式参数匹配的关键字。

    【讨论】:

      【解决方案3】:

      尽管不使用 kwargs 或检查模块(请参阅其他答案),您将无法获取参数,但您可以执行以下操作...

      class Obj(object):
          def __init__(self, **kwargs):
              self.__dict__.update(**kwargs)
      

      每个对象都有一个存储所有属性的字典,您可以通过self.__dict__ 访问它。然后,您只需使用update 设置该对象内部字典中的所有属性。

      请参阅this question 了解有关此方法的一些讨论。

      【讨论】:

        【解决方案4】:

        如果您想在方法的最顶部获取 args dict,在定义任何本地之前,这很简单:

        class Obj(object):
            def __init__(self,val1=None,val2=None,val3=None,val4=None):
               kwargs = dict(locals())
        

        以后要阅读这个字典,需要一些自省魔法:

        class Obj(object):
            def __init__(self,val1=None,val2=None,val3=None,val4=None):
        
               # feel free to add more locals
        
               loc = dict(locals())
               fun = sys._getframe().f_code
               kwargs = {x:loc[x] for x in fun.co_varnames[:fun.co_argcount]}
        

        您还可以通过添加如下函数使后者可重用:

        def getargs():
            f = sys._getframe(1)
            return {x:f.f_locals[x] for x in f.f_code.co_varnames[:f.f_code.co_argcount]}
        

        然后:

        class Obj(object):
            def __init__(self,val1=None,val2=None,val3=None,val4=None):
        
               # feel free to add more locals
        
               kwargs = getargs()
        

        我猜这是 cpython 特有的。

        【讨论】:

          【解决方案5】:

          是的,您可以将两者混合使用。 见下文:

          def method(a, b=1, *args, **kwargs):
              '''some code'''
          

          这是有效的。这里:

          'a' is a required argument
          'b' is a default argument
          'args' will have all the non-keyword arguments and
          'kwargs' will have all the keyword arguments.
          

          例子:

          method(1,2,3,4,5,test=6,test1=7)
          

          此调用将具有:

          a=1
          b=2
          args=(3,4,5)
          kwargs={'test':6,'test1':7}
          

          【讨论】:

            【解决方案6】:

            一种丑陋的解决方法:将额外的参数注入 kwargs 并在您想要循环所有关键字参数的地方使用它(PS 这是检查模块的示例用法,但建议用于生产用途):

            #!/usr/bin/env python
            
            import inspect
            
            def inject_defaults(func):
                """ injects '__defaults' key into into kwargs, 
                    so it can be merged with kwargs in the decorated method """
            
                args, varargs, varkwargs, defaults = inspect.getargspec(func)
                have_defaults = args[-len(defaults):]
                defaults_dict = dict(zip(have_defaults, defaults))
            
                def fun(*args, **kwargs):
                    kwargs['__defaults'] = defaults_dict
                    return func(*args, **kwargs)
            
                return fun
            
            @inject_defaults
            def f1(a,b,c, x=1, **kwargs):
                kwargs.update(kwargs['__defaults'])
                del kwargs['__defaults']
            
                for k, v in kwargs.items():
                    # here, x, y and z will appear
                    print(k, v)
            
            f1(1, 2, 3, y=3, z=2)
            # prints
            # ('y', 3)
            # ('x', 1)
            # ('z', 2)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-07-29
              • 2017-10-26
              • 1970-01-01
              • 2013-06-10
              • 2023-03-14
              • 2018-02-03
              • 1970-01-01
              相关资源
              最近更新 更多