1

私は気象データの複数のソースをチェックし、Android 用スクリプト レイヤーでいくつかのスクリプトを解析するスクリプトを作成しています。Google API が機能しなくなったため、これは古い天気モジュールのハッキングされた代替品です。

私は "weatherdata" というクラスを作成しました。クラスのすべてのインスタンスを "weatherobjects" というリストに追加したいと思います。

    for source in weatherobjects:
        source.check()

ここにキャッチがあります: 天気を取得する関数が呼び出されるたびに、オブジェクト__init__を破棄したり、リストをクリアしたりすることなく、オブジェクトがメソッド (技術的にはコンストラクター メソッドと呼ばれていると思いますか?) を実行します。これは意図的なものです。モジュールの存続期間中に関数が複数回呼び出され、オブジェクトが重複してリストに追加されると、問題が発生します。これは、メモリ リークの潜在的な原因のようです。

__init__メソッドは次のとおりです。

class weatherdata():
    def __init__(self, url, unit = 'f'):
        self.url = url
        self.unit = unit
        print(self) #debug statement, please ignore
        if self not in weatherobjects:
            weatherobjects.append(self)
        if self.url.count("yahoo"):
            self.yahoo = True
        else:
            self.yahoo = False
        self.check()

そして厄介な機能:

def fetch_weather(location=98661, hl='', weatherobjects= []):
    yahoo = weatherdata(yahoo_url, 'f')
    wunderground = weatherdata(wunderground_url, 'f')
    data = {}
    data['city'] = 'Vancouver'
    data['temperature'] = wunderground.temp
    data['conditions'] = 'foo'
    return data

コンテキストのシェル出力は次のとおりです。

>>> weatherobjects
[<__main__.weatherdata object at 0x01F8BDF0>, <__main__.weatherdata object at 0x02035B70>]
>>> for i in range(3):
...     fetch_weather()
...
{'city': 'Vancouver', 'conditions': 'foo', 'temperature': '66.7'}
{'city': 'Vancouver', 'conditions': 'foo', 'temperature': '66.7'}
{'city': 'Vancouver', 'conditions': 'foo', 'temperature': '66.7'}
>>> weatherobjects
[<__main__.weatherdata object at 0x01F8BDF0>, <__main__.weatherdata object at 0x02035B70>, <__main__.weatherdata object at 0x01FA2E10>, <__main__.weatherdata object at 0x01FA2FB0>, <__main__.weatherdata object at 0x02035C30>, <__main__.weatherdata object at 0x02035E10>, <__main__.weatherdata object at 0x02035DF0>, <__main__.weatherdata object at 0x02035D10>]
>>> len(weatherobjects)
8

ご覧のとおり、リストには多くの冗長性があります。__init__メソッドでこれを行うことは可能ですか?または、メイン関数に次のようなことをさせる必要がありますweatherobjects.append(foo)か?

4

3 に答える 3

4

カスタム クラスは、等しいとはどういう意味かを定義していません。__eq__2 つのインスタンスを比較する方法を Python に指示するメソッドを追加すると、inテストで重複を見つけることができます。

def __eq__(self, other):
    if not isinstance(other, self.__class__):
        return NotImplemented
    return self.url == other.url and self.unit == other.unit

メソッドを補完するには、__ne__メソッドも追加する必要があります。

def __ne__(self, other):
    return not self.__eq__(other)

作成後に weatherdata オブジェクトが変更されない (可変でない) 場合は、__hash__メソッドを追加して、インスタンスをリストではなくセットに格納できます。セットを使用すると、テストが高速化されinます。__hash__メソッドの例は次のとおりです。

def __hash__(self):
    return hash((self.url, self.unit))
于 2012-09-24T19:44:29.663 に答える
1

ソースをリストに追加する代わりに、辞書を検討できます。

weatherdata クラスがそれ自体を (def __repr__():おそらく) 一意に識別できる場合は、それを辞書に追加できます。

weatherobjects[str(self)] = self
于 2012-09-24T19:56:56.597 に答える
0

それで2年後、別のことに取り組んでいるときに答えを見つけて、これに戻ってきました。私のコードに関する他の問題はさておき、グローバルとしてではなく、(インスタンス化の前に) クラスでリストを定義するべきだったと思います。

私の望ましい動作は、Python Docs から取られたこの例のようなものでした:

 class Dog:

    tricks = []             # mistaken use of a class variable

    def __init__(self, name):
        self.name = name

    def add_trick(self, trick):
        self.tricks.append(trick)

    >>> d = Dog('Fido')
    >>> e = Dog('Buddy')
    >>> d.add_trick('roll over')
    >>> e.add_trick('play dead')
    >>> d.tricks                
    ['roll over', 'play dead']

犬は集団意識を持っていないため、これは不適切ですが、この動作はドキュメントで明示的に否定されていないため、そのまま使用します。私は自分のウェザーオブジェクトに集合意識を持たせたいと思っています。

したがって、このようなものの代わりに、

global weatherobjectslist
class weathersource():
    def __init__(self, weatherobjectlist):
        weatherobjectlist.append(self)

私の望ましい動作はこれによって生成されます:

class weathersource():
    weathersourcelist = []

    def __init__(self, name):
        self.weathersourcelist.append(self)
        self.name = name

これで、weathersource.weathersourcelist ですべてのオブジェクトのリストを確認できます。

これをより一般的に言えば、同じ動作といくつかの出力の例を次に示します。

>>> class person():
    people= []
    def __init__(self, name):
        self.people.append(self)
        self.name = name


>>> a,b,c = person('bob'), person('joe'), person('steve')

>>> for individual in person.people:
    print(individual.name)


bob
joe
steve
于 2014-11-07T19:32:08.147 に答える