3

私は現在、次のようなオブジェクトを作成しています。

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

私の質問は、2つを組み合わせて実行できますか?期待されるパラメーターを定義しながら、パラメーターをループして属性を設定できる場所はどこですか?自己文書化であり、他の開発者が使用されているkwargsを検索する必要がないため、期待されるパラメーターを定義するというアイデアが好きです。

かなり些細なことのように思えますが、XMLからオブジェクトを作成しているので、多くのパラメーターを渡すことになります。コードが乱雑になり、バグが発生します。

私はこれをグーグルで検索しましたが、何も見つかりませんでした。おそらく辞書とkwargsが一緒にkwargの例を指しているためです。

更新:より具体的には、渡されたパラメーターの辞書を取得して、kwargsをまったく使用する必要がないようにすることは可能ですか?

sudoコード:

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)
4

6 に答える 6

2

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'))
于 2012-12-27T16:28:49.290 に答える
1

関数のすべての引数の辞書を取得する良い方法はありません。構文は**kwargs、関数定義の明示的なパラメーターに一致するものではなく、追加のキーワード引数のみを収集します。

于 2012-12-27T16:27:03.657 に答える
1

kwargsまたはinspectモジュール(他の回答を参照)を使用せずにパラメーターを取得することはできませんが、次のようなことを行うことができます...

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

すべてのオブジェクトには、を介してアクセスできるすべての属性を格納する辞書がありますself.__dict__。次に、updateを使用して、そのオブジェクトの内部ディクショナリのすべての属性を設定します。

この方法の説明については、この質問を参照してください。

于 2012-12-27T16:29:46.333 に答える
1

ローカルを定義する前に、メソッドの最上部で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固有だと思います。

于 2012-12-27T16:38:56.333 に答える
0

はい、2つを混ぜることができます。下記参照:

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}
于 2012-12-27T16:24:37.863 に答える
0

一種の醜い回避策:kwargsに追加の引数を挿入し、すべてのキーワード引数をループする場所で使用します(PSこれはinspectモジュールの使用例ですが、本番環境での使用はお勧めしません):

#!/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)
于 2012-12-27T16:51:50.250 に答える