为什么这个类变量是None,即使它已被初始化?

时间:2017-01-28 02:26:26

标签: python kivy

我正在学习Kivy,并且这段代码的目的是缓存一个小部件,但我无法理解它的内容:

class WeatherRoot(BoxLayout):
    current_weather = ObjectProperty()

    def show_current_weather(self, location=None):
        self.clear_widgets()

        print(WeatherRoot.current_weather)
        print(self.current_weather)

        if location is None and self.current_weather is None:
            location = 'New York (US)'

        if location is not None:
            self.current_weather = Factory.CurrentWeather()
            self.current_weather.location = location
        self.add_widget(self.current_weather)

问题是current_weather,据我所知这是一个类变量,被定义为ObjectProperty,因为我没有实例变量(我认为是这样)覆盖此变量,当我引用self.current_weather时我指的是类变量,所以我认为self.current_weatherWeatherRoot.current_weather相同,但是当我打印这些变量时我不是期望两者都是ObjectProperty个实例,我得到了:

<ObjectProperty name=current_weather>
None

我的观点是,此变量永远不会是None,因为它是一个类变量,所以它始终是ObjectProperty,但似乎可能是None ,我不明白为什么。

这是此应用程序的GUI:

enter image description here

enter image description here

这是我的Kivy档案:

WeatherRoot:
<WeatherRoot>:
    AddLocationForm

<LocationButton>:
    on_press: app.root.show_current_weather(self.text)

<AddLocationForm>:
    orientation: 'vertical'
    search_input: search_box
    search_results: search_results_list
    BoxLayout:
        height: '40dp'
        size_hint_y: None
        TextInput:
            id: search_box
            size_hint_x: 50
            focus: True
            multiline: False
            on_text_validate: root.search_location()
        Button:
            text: 'Search'
            size_hint_x: 25
            on_press: root.search_location()
        Button:
            text: 'Current Search'
            size_hint_x: 25
    ListView:
        id: search_results_list
        adapter:
            ListAdapter(data=[], cls=main.LocationButton)
    Button:
        height: '40dp'
        size_hint_y: None
        text: 'Cancel'
        on_press: app.root.show_current_weather(None)

因此,当我按下取消按钮并且之前没有搜索过任何位置时,默认值是硬编码的,因为可以看到'New York (US)。当我先前搜索过某个位置并按下取消按钮时,会显示此位置。

有人可以解释一下这个变量current_weather是怎么回事吗?我认为不需要这个类变量,但是当我删除它时,我的应用程序崩溃了。

如果您需要,这是我的全部代码:

import json

from kivy.app import App
from kivy.network.urlrequest import UrlRequest
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.listview import ListItemButton
from kivy.factory import Factory

class WeatherRoot(BoxLayout):
    current_weather = ObjectProperty()

    def show_current_weather(self, location=None):
        self.clear_widgets()

        print(WeatherRoot.current_weather)
        print(self.current_weather)

        if location is None and self.current_weather is None:
            location = 'New York (US)'

        if location is not None:
            self.current_weather = Factory.CurrentWeather()
            self.current_weather.location = location
        self.add_widget(self.current_weather)

    def show_add_location_form(self):
        self.clear_widgets()
        self.add_widget(AddLocationForm())


class LocationButton(ListItemButton):
    pass


class AddLocationForm(BoxLayout):
    search_input = ObjectProperty()
    search_results = ObjectProperty()

    def search_location(self):
        search_template = 'http://api.openweathermap.org/' \
                          'data/2.5/find?q={}&type=like&APPID=' \
                          '090428d02304be901047796d430986e3'
        search_url = search_template.format(self.search_input.text)
        print(search_url)
        request = UrlRequest(search_url, self.found_location)

    def found_location(self, request, data):
        data = json.loads(data.decode()) if not isinstance(data, dict) else data
        cities = ['{} ({})'.format(d['name'], d['sys']['country'])
                  for d in data['list']]
        # self.search_results.item_strings = cities
        self.search_results.adapter.data.clear()
        self.search_results.adapter.data.extend(cities)
        self.search_results._trigger_reset_populate()


class WeatherApp(App):
    pass


WeatherApp().run()

1 个答案:

答案 0 :(得分:2)

属性为descriptors。虽然在类级别定义,但它们具有实例级行为,并且第一次近似将表现为实例变量。