7

多くの人がデフォルトのパラメータを受け取るPythonの関数を見たことがあると思います。例えば:

def foo(a=[]):
    a.append(3)
    return a

foo()を使用してこの関数を呼び出すと、出力は呼び出し後に毎回整数「3」を追加します。

この関数を定義すると、現在の環境で「foo」という名前の関数オブジェクトが定義され、この時点でデフォルトのパラメータ値も評価されます。パラメータなしで関数が呼び出されるたびに、評価されたパラメータ値がコードに従って変更されます。

私の質問は、この評価されたパラメータはどこにあるのかということです。 関数を呼び出すとき、それは関数オブジェクトにありますか、それともメソッドオブジェクトにありますか? Pythonのすべてがオブジェクトであるため、'a'->evaluatedパラメーターのname->valueバインディングを保持する場所が必要です。私はこの問題を考えすぎていますか?

4

5 に答える 5

11

他の人がすでに言ったように、デフォルト値は関数オブジェクトに保存されます。

たとえば、CPythonでは次のことができます。

>>> def f(a=[]):
...     pass
...
>>> f.func_defaults
([],)
>>> f.func_code.co_varnames
('a',)
>>>

ただし、co_varnamesargsの名前以外のものが含まれている可能性があるため、さらに処理する必要があり、これらの属性は他のPython実装には存在しない可能性があります。したがって、inspect代わりに、すべての実装の詳細を処理するモジュールを使用する必要があります。

>>> import inspect
>>> spec = inspect.getargspec(f)
>>> spec
ArgSpec(args=['a'], varargs=None, keywords=None, defaults=([],))
>>>

ArgSpec名前付きタプルであるため、属性としてすべての値にアクセスできます。

>>> spec.args
['a']
>>> spec.defaults
([],)
>>>

ドキュメントに記載されているように、defaultsタプルは常に。からの最後のn個の引数に対応しargsます。これにより、マッピングが可能になります。

dictを作成するには、次のようにします。

>>> dict(zip(spec.args[-len(spec.defaults):], spec.defaults))
{'a': []}
>>>
于 2012-04-12T10:03:50.130 に答える
5

関数オブジェクトにアタッチされています。以下を参照してくださいfoo.func_defaults

>>> foo()
>>> foo.func_defaults
([3],)
>>> foo()
>>> foo.func_defaults
([3, 3],)

aのマッピングを取得したい場合は、次のサイトに[]アクセスできますfoo.func_code

defaults = foo.func_defaults
# the args are locals in the beginning:
args = foo.func_code.co_varnames[:foo.func_code.co_argcount] 
def_args = args[-len(defaults):]  # the args with defaults are in the end
print dict(zip(def_args, defaults)) # {'a': []}

(しかし、どうやら、ヤクのバージョンの方が優れています。)

于 2012-04-12T09:36:52.683 に答える
4

これは関数オブジェクトのfunc_defaults:にあります

def f(a=[]): a.append(3)

print f.func_defaults # ([],)

f()

print f.func_defaults # ([3],)
于 2012-04-12T09:37:39.363 に答える
2

func_defaults関数オブジェクトの属性に格納されます。

>>> foo.func_defaults
([],)
>>> foo()
([3],)
于 2012-04-12T09:37:44.567 に答える
1

私は興味深い状況を見つけました:Python 2.5.2バージョンでは、関数'foo()'を試してください

>>> foo()
[1]
>>> foo()
[1]
>>> foo()
[1]

呼び出される関数のオブジェクトが異なるため:

>>> id(foo())
4336826757314657360
>>> id(foo())
4336826757314657008
>>> id(foo())
4336826757314683160

2.7.2バージョンの場合:

>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

この場合、オブジェクトは関数を呼び出すたびに同じです。

>>> id(foo())
29250192
>>> id(foo())
29250192
>>> id(foo())
29250192

異なるバージョンの問題ですか?

于 2012-04-12T14:31:01.883 に答える