プログラムの構造化。 Pythonでのクラスと関数
-
21-09-2019 - |
質問
私は、方程式を進化させる遺伝子技術を使用するプログラムを書いています。 私はパラレルPythonの提出」関数に関数「mainfunc」を提出することができるようにしたいです。 関数「mainfuncは、」ユーティリティ・クラスで定義された2つのまたは3つのメソッドを呼び出します。 彼らは他のクラスをインスタンス化し、さまざまなメソッドを呼び出します。 私は私がしたいこと1つの名前空間でそれがすべてだと思います。 私はいくつかをインスタンス化してきたように、関数「mainfunc」内部クラスの(多分それはすべてをする必要があります)。 I ')は(生成]ユーティリティメソッドを呼び出します。我々は、実行のそれの連鎖をたどるした場合 それは、コード内のクラスとメソッドのすべてを伴うだろう。
次に、方程式はツリーに格納されています。たびツリーは、生成された変異したり、クロスさ 繁殖させ、ノードは、彼らが木の辞書属性からアクセスできるように、新しいキーを与えられる必要があります。クラスのKEYSEQ」はこれらのキーを生成します。
パラレルPythonでは、私はPPの「提出」関数に「mainfunc」の複数のインスタンスを送信するつもりです。各アクセス「KEYSEQ」にできるようにしています。彼らはすべてのKEYSEQの同じインスタンスにアクセスした場合に返さ木上のノードのいずれもが同じキーを持っていたので、それはいいだろうが、私は必要に応じていることを周りに得ることができます。
ので:私の質問はmainfuncにすべてを詰めるについてです。 感謝 私はmainfuncのすべてが含まれていない場合(編集)、私は様々な場所で様々なarguementsを渡すことによって依存する機能などについてのPPを伝えるために試してみて下さい。私はそれを避けるためにしようとしています。
ks.nextは、()内で呼び出された場合、(後半編集)NameError「を生成()関数は、それがエラーを返し 『:』定義されていないグローバル名 『KSを』
class KeySeq:
"Iterator to produce sequential \
integers for keys in dict"
def __init__(self, data = 0):
self.data = data
def __iter__(self):
return self
def next(self):
self.data = self.data + 1
return self.data
class One:
'some code'
class Two:
'some code'
class Three:
'some code'
class Utilities:
def generate(x):
'___________'
def obfiscate(y):
'___________'
def ruminate(z):
'__________'
def mainfunc(z):
ks = KeySeq()
one = One()
two = Two()
three = Three()
utilities = Utilities()
list_of_interest = utilities.generate(5)
return list_of_interest
result = mainfunc(params)
解決
あなたはmainfunc
のすべてのインスタンスが同じKeySeq
オブジェクトを使用する場合は、デフォルトのパラメータ値のトリックを使用することができます:
def mainfunc(ks=KeySeq()):
key = ks.next()
長いあなたが実際ks
に対するすべての呼び出しは、関数が定義されたときに作成されたmainfunc
のインスタンスを使用します、KeySeq
の値を渡していない限ります。
ここで、なぜ、ケースであなたは知らないです:関数はオブジェクトです。それは属性があります。その属性の一つはfunc_defaults
という名前です。それはデフォルトを持ってその署名内のすべての引数のデフォルト値を含むタプルです。関数を呼び出すと、デフォルトを持っている引数の値を提供しない場合は、関数がfunc_defaults
から値を取得します。あなたがmainfunc
のために価値を提供することなくks
を呼び出すときだから、それはKeySeq()
タプルのうち、func_defaults
インスタンスを取得します。これは、mainfunc
のそのインスタンスのために、常に同じKeySeq
インスタンスです。
さて、あなたが送信するつもりだと言って、「PPのmainfunc
関数にsubmit
の複数のインスタンスを。」あなたは本当に複数のインスタンスを意味していますか?もしそうなら、私が説明してるのメカニズムはしません仕事ます。
しかし、それは機能の複数のインスタンスを作成するトリッキーだ(とあなたが投稿したコードにはありません)。たとえば、この機能はg
のそれは呼ばれていますたびに新しいインスタンスを返すん:
>>> def f():
def g(x=[]):
return x
return g
>>> g1 = f()
>>> g2 = f()
>>> g1().append('a')
>>> g2().append('b')
>>> g1()
['a']
>>> g2()
['b']
私は引数なしでg()
を呼び出すと、は、それがそのfunc_defaults
タプルからデフォルト値(最初は空のリスト)を返します。 g1
とg2
がg
機能の異なるインスタンスであるので、x
引数のデフォルト値は、上記の実証ます。
デフォルト値のトリッキーな副作用を使用するよりも、これはより明確にするためにたい場合は、ここでそれを行うための別の方法があります:
DEF mainfunc(): そうでない場合はhasattr(mainfunc、 "KS"): SETATTR(mainfunc、 "KS"、KEYSEQ()) キー= mainfunc.ks.next()
最後に、コードをあなたが投稿見晴らしをしたという超重要な点:あなたはつもりならに共有データ上で並列処理を行うことは、タッチそのデータニーズは、ロックをコード実装すること。パラレルPythonドキュメントでcallback.py
の例を見て、ロックがSum
クラスで使用されている方法を見て、なぜます。
他のヒント
これは、道というあなたのプログラムを構築するために罰金です。コマンドラインユーティリティの多くは、同じパターンに従います。
#imports, utilities, other functions
def main(arg):
#...
if __name__ == '__main__':
import sys
main(sys.argv[1])
そのようにあなたがそれをインポートすることにより、他のモジュールからmain
関数を呼び出すことができ、またはコマンドラインから実行することができます。
Pythonでのクラスのあなたの考え方は、私が考えるに聞こえるではありません。おそらく、基本を見直す良いでしょう。このリンクは役立ちます。