可変のデフォルト引数値の適切な使用法の質問に答えて、次の例を示します。
変更可能なデフォルトは、自分で作成した使いやすくインポート可能なコマンドをプログラミングするのに役立ちます。可変のデフォルトメソッドは、最初の呼び出しで初期化できる(クラスと非常によく似ている)が、グローバルに頼る必要もなく、ラッパーを使用する必要もなく、インスタンス化する必要もなく、関数内にプライベートな静的変数を持つことになります。インポートされたクラスオブジェクト。あなたが同意することを願っていますので、それはそれ自体がエレガントです。
次の2つの例を検討してください。
def dittle(cache = []):
from time import sleep
if type(cache) != list or cache !=[] and (len(cache) == 2 and type(cache[1]) != int):
print(" User called dittle("+repr(cache)+").\n >> Warning: dittle() takes no arguments, so this call is ignored.\n")
return
if not cache:
print("\n cache =",cache)
print(" Initializing private mutable static cache. Runs only on First Call!")
cache.append("Hello World!")
cache.append(0)
print(" cache =",cache,end="\n\n")
cache[1]+=1
outstr = " dittle() called "+str(cache[1])+" times."
if cache[1] == 1:outstr=outstr.replace("s.",".")
print(outstr)
print(" Internal cache held string = '"+cache[0]+"'")
print()
if cache[1] == 3:
print(" Let's rest for a moment.")
sleep(2.0)
print(" Wheew! Ready to continue.\n")
sleep(1.0)
elif cache[1] == 4:
cache[0] = "It's Good to be Alive!"
if __name__ == "__main__":
for cnt in range(2):dittle()
print(" Attempting to pass an list to dittle()")
dittle([" BAD","Data"])
print(" Attempting to pass a non-list to dittle()")
dittle("hi")
print(" Calling dittle() normally..")
dittle()
print(" Attempting to set the private mutable value from the outside.")
dittle([" I am a Grieffer!\n (Notice this change will not stick!)",-7])
print(" Calling dittle() normally once again.")
dittle()
dittle()
このコードを実行すると、dittle()関数は最初の呼び出しでは内部化されますが、追加の呼び出しでは内部化されないことがわかります。呼び出し間の内部静的ストレージにプライベート静的キャッシュ(可変デフォルト)を使用し、ハイジャックの試みを拒否します静的ストレージは、悪意のある入力に対して回復力があり、動的条件(ここでは関数が呼び出された回数)に基づいて動作できます。
可変デフォルトを使用するための鍵は、メモリ内の変数を再割り当てすることを何もしないで、常に変数をその場で変更することです。
この手法の潜在的な能力と有用性を実際に確認するには、この最初のプログラムを「DITTLE.py」という名前で現在のディレクトリに保存してから、次のプログラムを実行します。新しいdittle()コマンドをインポートして使用します。覚えておく手順や、ジャンプするフープをプログラミングする必要はありません。
これが2番目の例です。これをコンパイルして、新しいプログラムとして実行します。
from DITTLE import dittle
print("\n We have emulated a new python command with 'dittle()'.\n")
dittle()
dittle()
dittle()
dittle()
dittle()
さて、それは可能な限り滑らかできれいではありませんか?これらの変更可能なデフォルトは本当に便利です。
========================
しばらく私の答えを振り返った後、私は可変のデフォルトの方法を使用することと同じことを達成する通常の方法を使用することの違いを明確にしたかどうかわかりません。
通常の方法は、Classオブジェクトをラップする(そしてグローバルを使用する)インポート可能な関数を使用することです。したがって、比較のために、ここでは、可変のデフォルトメソッドと同じことを実行しようとするクラスベースのメソッドを示します。
from time import sleep
class dittle_class():
def __init__(self):
self.b = 0
self.a = " Hello World!"
print("\n Initializing Class Object. Executes on First Call only.")
print(" self.a = '"+str(self.a),"', self.b =",self.b,end="\n\n")
def report(self):
self.b = self.b + 1
if self.b == 1:
print(" Dittle() called",self.b,"time.")
else:
print(" Dittle() called",self.b,"times.")
if self.b == 5:
self.a = " It's Great to be alive!"
print(" Internal String =",self.a,end="\n\n")
if self.b ==3:
print(" Let's rest for a moment.")
sleep(2.0)
print(" Wheew! Ready to continue.\n")
sleep(1.0)
cl= dittle_class()
def dittle():
global cl
if type(cl.a) != str and type(cl.b) != int:
print(" Class exists but does not have valid format.")
cl.report()
if __name__ == "__main__":
print(" We have emulated a python command with our own 'dittle()' command.\n")
for cnt in range(2):dittle()
print(" Attempting to pass arguments to dittle()")
try:
dittle(["BAD","Data"])
except:
print(" This caused a fatal error that can't be caught in the function.\n")
print(" Calling dittle() normally..")
dittle()
print(" Attempting to set the Class variable from the outside.")
cl.a = " I'm a griefer. My damage sticks."
cl.b = -7
dittle()
dittle()
このクラスベースプログラムを現在のディレクトリにDITTLE.pyとして保存してから、次のコードを実行します(これは前と同じです)。
from DITTLE import dittle
dittle()
dittle()
dittle()
dittle()
dittle()
2つの方法を比較することにより、関数で可変デフォルトを使用する利点がより明確になるはずです。可変のデフォルトメソッドはグローバルを必要とせず、その内部変数を直接設定することはできません。そして、可変メソッドは、知識のある渡された引数を1サイクル受け入れてから肩をすくめましたが、Classメソッドは、その内部変数が外部に直接公開されているため、永続的に変更されました。プログラミングが簡単な方法はどれですか?それは、方法に対するあなたの快適さのレベルとあなたの目標の複雑さに依存すると思います。