1

我正在编写一个脚本来检查多个来源的天气数据,然后将它们解析为 Android 脚本层上的一些脚本。谷歌 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

这是上下文的一些 shell 输出:

>>> 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__告诉 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

所以两年后,我在做其他事情时找到了答案,然后回到这个。撇开我的代码的其他问题不谈,我认为我应该在类中定义列表(在实例化之前),而不是作为一个全局列表。

我想要的行为就像这个例子,取自 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 回答