0

Pythonで渡されたパラメータの名前を取得することは可能ですか?

具体的には、私はこれを行うことができるようにしたい:

def a(name):
    print "the actual passed parameter is %s" %(???)

それは何を解決しますか?

したがって、bag_list やbasket_list などのバッグやバスケットにコインを配布する必要がある場合、「バッグ」や「バスケット」などの明示的な識別子を送信する必要はありません。

これは、私が現在それを回避する方法です。私は現在、この目的のために(グローバル)辞書を使用しています-

ID = {'bag': bag_list, 'basket': basket_list}

def a(name, id):
   dist_list = ID[id]

また、変数名を文字列に変換することにも要約されます。これは、目的の動作を次のようにモデル化することもできるためです。

def a(name):
    name = ???get variable name as string magically???
    if name.startswith('bag'): 
         dist_list = ID['bag']
    else:
         dist_list = ID['basket']

再モデル化された質問はhttps://stackoverflow.com/a/9121991/1397945で包括的に回答されていますが、これを再投稿しています

  • いくつかの変更があった場合に備えて &
  • Perl や Tcl などの他のスクリプト言語でこれを行うことができるかどうか。
  • さらに、モデリングの 2 つの方法が異なる場合、または異なる方法でアプローチできる場合はなおさらです。

ありがとう。

4

4 に答える 4

3

それは可能ですが、私はこれをむしろ汚いハックと見なします。私の解決策を読んだ後、本当にこの道を進みたいのであれば、一歩下がってよく考えてください。

def a(name):
    global_variables = globals()
    try:
        name_of_passed_in_variable = [x for x in global_variables if id(global_variables[x]) == id(name)][0]
    except Exception:
        name_of_passed_in_variable = "unknown"
    print name_of_passed_in_variable, name

my_name = "Tom"
a(my_name)

a("Mike")

second_name = my_name
a(second_name)

出力が得られます:

my_name Tom
unknown Mike
my_name Tom

私の例では、このアプローチの欠点も見ることができます。

  • 変数を代入せずに文字列を直接渡すと、名前を判別できません
  • 同じ変数への参照が複数ある場合、どの名前が取得されるかわかりません

後者の問題については、もちろんそれに対処するロジックを実装することもできます。あるいは、これはまったく問題にならないかもしれません。

于 2013-01-31T06:34:23.027 に答える
2

あなたが抱えている問題は、議論の違いだと思います。名前が呼び出し元によって明示的に示されるキーワード引数と、単純な位置引数があります。あなたはこれを行うことができます、

def a(**kwargs):
    if 'bag' in kwargs:
         dist_list = ID['bag']
    else:
        dist_list = ID['basket']

そのように変数を渡す必要があります。

a(bag=...)

startswithまたは、パラメーターバッグまたはバスケットを実行できるかどうかを確認したい場合は、

def a(**kwargs):
    if any(k.startswith('bag') for k in kwargs.iterkeys()):
        dist_list = ID['bag']
    elif any(k.startswith('basket') for k in kwargs.iterkeys()):
        dist_list = ID['basket']
    else:
        raise Exception('a requires argument starting with `basket` or `bag`')

しかし、どのキーがバッグまたはバスケットで始まるかを判断する問題があるので、私はおそらくそうするでしょう.

def a(**kwargs):
    valid_key = [k for k in kwargs.iterkeys() if k.startswith('bag') or k.startswith('basket')][0]
    if valid.key.startswith('bag'):
         dist_list = ID['bag']
    elif valid.key.startswith('basket'):
        dist_list = ID['basket']
    else:
        raise Exception('a requires argument starting with `basket` or `bag`')
于 2013-01-31T06:16:06.967 に答える
1

このようなものはあなたのユースケースに合っていますか?

>>> class Inventory(object):
    basket = 0
    bag = 0
    def add_coins(self, **kwargs):
        if 'bag' in kwargs:
            self.bag += kwargs['bag']
        if 'basket' in kwargs:
            self.basket += kwargs['basket']


>>> i = Inventory()
>>> i.add_coins(bag=6)
>>> i.bag
6
>>> i.add_coins(bag=2)
>>> i.bag
8
>>> i.basket
0
于 2013-01-31T06:10:41.350 に答える
1

一般に、Python は名前が添付されたオブジェクトを渡さないため、必要なことは不可能です。

関数を呼び出す場合、ユーザーが常にキーワード引数を使用して関数を呼び出すと、名前と値のペアを含む辞書を取得できます。

だからあなたはこれを行うことができます:

def a(**kwargs):
    if len(kwargs) != 1:
        raise ValueError("only pass a single keyword arg starting with 'bag' or 'basket'")
        # Above line is Python 3.x syntax; below line is Python 2.x syntax
        # raise ValueError, "only pass a single keyword arg starting with 'bag' or 'basket'"
    name, value = list(kwargs.items())[0]
    if name.startswith('bag'): 
         dist_list = ID['bag']
    else:
         dist_list = ID['basket']
    # I don't know what you want next, but let's say you want to append:
    dist_list.append(value)

次に、ユーザーは次のように関数を呼び出す必要があります。

a(bag=3)
a(basket=5)

編集: コードは Python 3.x に対して正しくなり、Python 2.x 用に簡単に変更できます (コメントを参照)。

編集:考えてみると、これを一般化できます。に改名することにID_containersます。

def a(**kwargs):
    for key, value in kwargs.items():
        if key in _containers:
            _containers[key].append(value)
        else:
            raise ValueError("invalid container name '%s'" % key)

1 回の呼び出しで複数のコンテナーを追加できるようになりました。ただし、ユーザーが次のようなことを行う可能性があるため、少し注意が必要です。

a(bag=1, basket=2, bag=3)

辞書に設定されるため、bag=1は決して起こりません。(ディクショナリをオーバーロードされた関数を持つカスタム クラスに置き換えるトリッキーな方法があるかもしれませんが、その方法は狂気の沙汰です...トリッキーなコードはお勧めしません。)bag3

あまり良くはありませんが、で始まる名前が必要な場合は、次のbagようにします。

def a(**kwargs):
    for key, value in kwargs.items():
        found = False
        for container_name in _containers:
            if key.startswith(container_name):
                _containers[container_name].append(value)
                found = True
                break
        if not found:
            raise ValueError("no container name matched '%s'" % key)
于 2013-01-31T06:12:02.290 に答える