コードに悪臭がします。少し空気を抜く必要があるのかもしれませんが、今は悩まされています。
出力を比較できるように、3 つの放射伝達モデリング (RTM) アプリケーションを実行するために 3 つの異なる入力ファイルを作成する必要があります。このプロセスは何千もの入力セットに対して繰り返されるため、Python スクリプトで自動化しています。
入力パラメーターを、他の 3 つの関数に渡すことができる汎用の Python オブジェクトとして保存したいと思います。これらの関数は、その一般的なオブジェクトを、それぞれが担当する RTM ソフトウェアを実行するために必要な特定のパラメーターに変換します。これは理にかなっていると思いますが、私のアプローチを自由に批判してください。
RTM ソフトウェアの各部分には、多くの可能な入力パラメーターがあります。それらの多くは重複しています。それらのほとんどは適切なデフォルトに保たれていますが、簡単に変更できるはずです。
簡単なことから始めましたdict
config = {
day_of_year: 138,
time_of_day: 36000, #seconds
solar_azimuth_angle: 73, #degrees
solar_zenith_angle: 17, #degrees
...
}
多くのパラメーターがあり、グループにきれいに分類できるため、dict
内で s を使用することを考えましたdict
:
config = {
day_of_year: 138,
time_of_day: 36000, #seconds
solar: {
azimuth_angle: 73, #degrees
zenith_angle: 17, #degrees
...
},
...
}
私はすきです。しかし、冗長なプロパティがたくさんあります。たとえば、太陽の方位角と天頂角は、もう一方がわかっている場合に見つけることができますが、なぜ両方をハードコーディングするのでしょうか? そこで、python の builtin を調べ始めましproperty
た。オブジェクト属性として保存すると、データを使って気の利いたことができます。
class Configuration(object):
day_of_year = 138,
time_of_day = 36000, #seconds
solar_azimuth_angle = 73, #degrees
@property
def solar_zenith_angle(self):
return 90 - self.solar_azimuth_angle
...
config = Configuration()
しかし、今では 2 番目のdict
例の構造を失ってしまいました。
一部のプロパティは私の例よりも単純ではなく、solar_zenith_angle
それが属している属性のグループ外の他の属性へのアクセスが必要になる場合があることに注意してください。たとえばsolar_azimuth_angle
、年、時刻、緯度、経度がわかれば計算できます。
私が探しているもの:
すべての値が統一された方法でアクセスでき、適切に構造化され、属性 (実際の値) またはプロパティ (他の属性から計算される) として存在する構成データを格納する簡単な方法。
ちょっと退屈な可能性:
前に概説した dicts の dicts にすべてを格納し、他の関数をオブジェクトに対して実行して、計算可能な値を計算しますか? これは面白くない。またはきれい。私には、面倒でイライラするように聞こえます。
動作する醜いもの:
長い間さまざまな戦略を試し、ほとんどどこにも行き着かなかった後、うまくいくと思われる1つの解決策を思いつきました。
私のクラス: (少しファンキー、えー、ファンキーなにおいがします。間違いなく。)
class SubConfig(object):
"""
Store logical groupings of object attributes and properties.
The parent object must be passed to the constructor so that we can still
access the parent object's other attributes and properties. Useful if we
want to use them to compute a property in here.
"""
def __init__(self, parent, *args, **kwargs):
super(SubConfig, self).__init__(*args, **kwargs)
self.parent = parent
class Configuration(object):
"""
Some object which holds many attributes and properties.
Related configurations settings are grouped in SubConfig objects.
"""
def __init__(self, *args, **kwargs):
super(Configuration, self).__init__(*args, **kwargs)
self.root_config = 2
class _AConfigGroup(SubConfig):
sub_config = 3
@property
def sub_property(self):
return self.sub_config * self.parent.root_config
self.group = _AConfigGroup(self) # Stinky?!
それらの使用方法:(私が望むように動作します)
config = Configuration()
# Inspect the state of the attributes and properties.
print("\nInitial configuration state:")
print("config.rootconfig: %s" % config.root_config)
print("config.group.sub_config: %s" % config.group.sub_config)
print("config.group.sub_property: %s (calculated)" % config.group.sub_property)
# Inspect whether the properties compute the correct value after we alter
# some attributes.
config.root_config = 4
config.group.sub_config = 5
print("\nState after modifications:")
print("config.rootconfig: %s" % config.root_config)
print("config.group.sub_config: %s" % config.group.sub_config)
print("config.group.sub_property: %s (calculated)" % config.group.sub_property)
動作: (予想どおり、上記のすべてのコードの実行の出力)
Initial configuration state:
config.rootconfig: 2
config.group.sub_config: 3
config.group.sub_property: 6 (calculated)
State after modifications:
config.rootconfig: 4
config.group.sub_config: 5
config.group.sub_property: 20 (calculated)
気に入らない理由:
メイン オブジェクト内のクラス定義に構成データを格納することは、__init__()
エレガントに感じられません。特に、そのような定義の直後にそれらをインスタンス化する必要があります。うーん。確かに、親クラスでそれを処理できますが、コンストラクターでそれを行う...
同じクラスをメイン オブジェクトの外に格納することも、エレガントに感じられません。内部クラスのプロパティは、 (またはその内部の兄弟)Configuration
の属性に依存する可能性があるためです。Configuration
私はすべての外で関数を定義することができたので、内部には次のようなものがあります
@property
def solar_zenith_angle(self):
return calculate_zenith(self.solar_azimuth_angle)
しかし、私は次のようなことをする方法を理解できません
@property
def solar.zenith_angle(self):
return calculate_zenith(self.solar.azimuth_angle)
(私がそれについて賢くしようとすると、私はいつも遭遇します<property object at 0xXXXXX>
)
では、これを行う正しい方法は何ですか?何か基本的なことを見逃しているのでしょうか、それとも非常に間違ったアプローチをとっているのでしょうか? 誰かが賢い解決策を知っていますか?
ヘルプ!私のpythonコードは美しくありません!私は何か間違ったことをしているに違いない!