なぜデフォルトの引数により評価して定義時間Python?
-
22-07-2019 - |
質問
私は非常に困難な時期に理解し、サプライチェーンのなかで多様な問題にアルゴリズムです。その後、極力簡単にすることで、機能の一歩一歩していることが分かった評価のデフォルトの引数はPythonではないとして行動できたので、良かったです。
コードは以下のとおりです:
class Node(object):
def __init__(self, children = []):
self.children = children
問題は毎のインスタンスノード種類株式と同じ children
属性の場合、属性の指定がない明示的にど
>>> n0 = Node()
>>> n1 = Node()
>>> id(n1.children)
Out[0]: 25000176
>>> id(n0.children)
Out[0]: 25000176
かわからないの論理はこのデザインを決定するのかなぜPythonのデザイナーを決定するデフォルトの引数に対する評価で定義す。これは、非常に容易なった。
解決
に代替するかなりヘビー級--保存"デフォルトの引数の値の関数オブジェクトとして"thunks"のコードに実行されるまで毎時間の関数が呼び出されずに指定された値を持つ引数に--そうであったが、それができなくなっく早く結合(結合でdef時間はしばしばと考えている。例えば、Pythonに存在する:
def ack(m, n, _memo={}):
key = m, n
if key not in _memo:
if m==0: v = n + 1
elif n==0: v = ack(m-1, 1)
else: v = ack(m-1, ack(m, n-1))
_memo[key] = v
return _memo[key]
...作成memoized機能のようでも情報にアクセスされる方です。同様に:
for i in range(len(buttons)):
buttons[i].onclick(lambda i=i: say('button %s', i))
を---簡単な i=i
, に依拠し、初期の結合定義時間)のデフォルトargの値は、triviallyシンプルな方法を早期に結合する。なので、現在のルールは簡単な単純なくご利用いただいていない方が非常に簡単に説明し理解する:したい場合は遅く結合の表現の価値を評価し、その表現の機能体したい場合は初期の結合評価としてのデフォルト値のばいけない。
その代わりに強遅結合の両方の状況などをご提供すること柔軟性、力ます。フープなどを包んだ機能への閉鎖工場)ごとに必要な初期結合して、上記の例--そしてさらに重量定型強制は、プログラマによるこの仮想的なデザイン決定を超えて"見えない"ものの発生を繰り返し評価するthunksにする。
つまり、"あるべき、好ましくは、明文について教えてください[1]":いたい場合、下旬に結果が既に完全に明らかな成長はないということだ。ですべての機能コードが実行時に通話時間もちろんのこと、全ての評価 あり レバ);このデフォルト-arg評価を早期に結合す明らかな方向に結合して(プラス!-) よつき、明らかな方法を下旬に結合とは明らかに早く結合(マイナスの状況の中!-).
[1]:"このような方法がないことは明らかでませんがオランダ語"
他のヒント
の問題があります。
あまりにも高い評価としての機能を初期化子 毎時間の関数が呼び出され.
0
簡単なリテラルです。評価では、一度使用します。int
機能(リスト)について評価するのに必要として初期化.
の構築 []
は文字通りのように、 0
, しているため、"この正確なオブジェクト".
問題は、一人ってくれればと願っていると list
としての"評価この機能は私にとってください、したオブジェクトを取得しますが、初期化".
この破砕負担を追加する必要 if
算書い評価。すべての引数としてのリテラルとはできません追加機能としての評価の一部としての機能を評価。
また、より根源的には、技術的に 不可 実行引数はデフォルトとしての機能を評価する
考える一瞬を再帰怖いのこのような真円度.ということかその代わりにデフォルト値がリテラルをできる機能が評価される各パラメータのデフォルトの値が必要です。
[このことは平行方 collections.defaultdict
ます。]
def aFunc( a=another_func ):
return a*2
def another_func( b=aFunc ):
return b*3
ではそうすることが可能で another_func()
?のデフォルト b
, でを行い、評価しなければならな aFunc
, が求められる<エバール>の another_func
.てへ。
もちろんお客様の状況では分かりにくい。いてを参照してください、その評価デフォルト(<%=args%>等:argsは毎時間のうち重実行時の負荷をかけます。
また知っておきたい、その場合はコンテナの種類が発生している可能性がありがきを回避すでに明示的なもの:
def __init__(self, children = None):
if children is None:
children = []
self.children = children
の回避策のため、この ここで説明されてい (固体):
class Node(object):
def __init__(self, children = None):
self.children = [] if children is None else children
という回答からvon Löwis、それらの機能を定義するコードオブジェクトによるアーキテクチャに対するPythonとができない施設作業につ参照型のようにこのデフォルトの引数になります。
しかし、ここ逆説的にも、またどのようにPython実装のデフォルトの引数です。
機能のオブジェクトです。積荷時点で、Pythonを作成し、関数オブジェクトの評価は、デフォルトの def
声明は、それをタプルを追加したタプルの属性としての機能の名前 func_defaults
.そして、関数が呼び出される場合、通話なの値を提供する、Pythonラブ(デフォルトの値の func_defaults
.
たとえば、次のようになります。
>>> class C():
pass
>>> def f(x=C()):
pass
>>> f.func_defaults
(<__main__.C instance at 0x0298D4B8>,)
すべての通話を f
を提供しない引数の同一のインスタンス C
, のため、デフォルトの値です。
どなぜPythonはこのようになっております:でも、そのタプル え を含む機能するようになると呼ばれる毎にデフォルトの引数の値が必要となります。から直ちに明らかな問題の性能、まず身近なところで行われている宇宙は、特別の場合には、蓄積リテラル値ではなく機能を単に変更可能な型を避ける不必要な機能を発信します。もちろんあり性能を意味三昧を。
実際の動作は本当にシンプルです。あな回避策をいただく場合 したい デフォルト値による機能でランタイム:
def f(x = None):
if x == None:
x = g()
これはpythonからを書式および実行を意味します。a def書が発生する一定の時点から実行します。時のpythonインタプリタが、この点で評価コードとし、その中で使用するコードオブジェクトからのボディに機能を実行後、時を呼び出す機能です。
この単純分割と機能を宣言と関数の本体。この宣言を実行きに到達したものです。車体は実行時に通話時間として計算します。この宣言を実行すがに達したとして購入することができます複数の機能によるループ.
funcs = []
for x in xrange(5):
def foo(x=x, lst=[]):
lst.append(x)
return lst
funcs.append(foo)
for func in funcs:
print "1: ", func()
print "2: ", func()
別の機能が作成されると、別リスト作成され、関数の宣言を実行しました。各ループによ funcs
, 同じ機能が実行され倍各通過し、同じリスト。この結果:
1: [0]
2: [0, 0]
1: [1]
2: [1, 1]
1: [2]
2: [2, 2]
1: [3]
2: [3, 3]
1: [4]
2: [4, 4]
それまでの回避策、param=なし情トの身体の場合の値はNoneでの慣用句ます。ちょっと醜いものの、簡潔で力強い、回避策のものは痛い。
編集追加:り議論が、effbotの記事はこちら http://effbot.org/zone/default-values.htm, の言語を参考にこちら: http://docs.python.org/reference/compound_stmts.html#function
Python関数定義でコードのように、すべてのコードそんな"魔法"のようにいくつかの言語です。たとえば、Javaできる"を参照してください今、"何かを定義"後に":
public static void foo() { bar(); }
public static void main(String[] args) { foo(); }
public static void bar() {}
がPython
def foo(): bar()
foo() # boom! "bar" has no binding yet
def bar(): pass
foo() # ok
なので、デフォルトの引数を評価し、その行のコードの評価!
でも、誰かがポート作成コンポーネン答えはなぜなの-p
かった。かを実装する、現在の行動が必要なのか?"す新しいオブジェクトを作成中の機能はできません"uncreate"(削除できますし、なにものとします。.
んで反対意見、addessingの引数にします。
評価するデフォルトの引数の機能を実行する悪い。
だが、こうした難しいと思います。場合はデフォルトの引数の課題のように foo='some_string'
本当に追加入金額の架では難しいことだと思いることができる課題への変更不能なリテラルprecomputeします。
したい場合はデフォルトの課題に変更可能なオブジェクトのような
foo = []
, は、利用foo = None
, く、次いfoo = foo or []
に機能します。
かもしれないが、これunproblematic個別のインスタンスとしてデザインパターンなので非常にエレガントです。で定型コードとい隠すデフォルトの引数の値です。パターンのように foo = foo or ...
働いていない場合 foo
できるオブジェクトのようにしても済む配列未定義の真理値です。や場 None
ある意味のある引数で渡される可能性がある意図的な使用としてセンチネルは、この回避策になっ醜い.
現在の行動は変更可能なデフォルトのオブジェクト すべ 共有する待に機能します。
をやらせていただきたいと思い参照で起きても、本利用の場合はるかにインパクトは小さいも頻繁により変更可能なオブジェクトを作成した時に関数が呼び出されます。私ものと思われるより高度な利用の場合は偶発的なデフォルトの課題とした空容器の共通のgotchaのための新たなPythonプログラマー.そのため、原理の少なくとも驚きを与がデフォルトの引数の値が評価されるべきであるときの機能が実行されます。
また、いように思われが簡単に回避策のための可変オブジェクトができるようにしてくれます。機能電話:initialiseして外部の機能です。
いいこと悪いデザイン決定します。私の推測であって選ばれたので、その実装は、実は簡単で有効なもの)を使用。残念なことに、とは思わないまって、コアPython開発者を避けるためには繰り返しの逆解をPython3を紹介する。