Я учусь Kivy, и цель, если этот кусок кода кэшировать виджет, но у меня возникают проблемы с пониманием того, что происходит с ним:Почему эта переменная класса None, даже если она была инициализирована?
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_weather
- это то же самое, что и WeatherRoot.current_weather
, но с тех пор, когда я напечатал эти переменные, я ожидал, что оба экземпляра будут ObjectProperty
, и я получил:
<ObjectProperty name=current_weather>
None
Я считаю, что эта переменная никогда не будет None
, потому что это переменная класса, так что всегда ObjectProperty
, но мне кажется, что можно быть None
, и я не понимаю, почему.
Это графический интерфейс этого приложения:
Это мой 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()
, когда вы говорите, что __Properties являются дескрипторами__, вы заявляете, что свойства Kivy определены как дескрипторы? Или вы имеете в виду, что это свойства Python, то есть метод, к которому можно получить доступ, как если бы это был атрибут? – lmiguelvargasf
Свойства Kivy являются дескрипторами в том смысле, что они реализуют протокол дескриптора, как в связанной документации. Они похожи на обычные свойства python в том, как они себя ведут, но их реализация отличается (и включает в себя дополнительное поведение). – inclement