__init__ значения против значения экземпляра

#python #python-3.x #kivy

#python #python-3.x #kivy

Вопрос:

Я новичок в python и kivy, я застрял в понимании __init__ создания экземпляра переменной, мой код выглядит следующим образом:

 from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout

spots={}

class spot(Button):
    '''
    classdocs
    '''
    def __init__(self, **kwargs):
        '''
        Constructor
        '''
        super(spot,self).__init__(**kwargs)
        self.ismine=False
        self.text="X"

class game(BoxLayout):        

    def attachtogrid(self):
        self.m.clear_widgets()
        spots.clear()
        for r in range(0,25):
            for c in range(0,25):
                id=str(r) "," str(c)
                spots[id]=id
                self.m.add_widget(spot(text=id)) 
 

Моя проблема в том, что, хотя я передаю значение идентификатора в свойство text (последняя строка кода), я все равно получаю «X» в виде текста, который используется по умолчанию в классе spot; и если я удалю текст по умолчанию
(self.text =»X») из класса, текст идентификатора будет работать.

Не могли бы вы уточнить приведенные выше значения по умолчанию и различия в создании экземпляра. Спасибо.

Ответ №1:

Когда вы передаете значение id ключу text , оно будет сохранено в виде пары ключ: значение в словаре kwargs внутри __init__ .

Таким образом, вы можете получить к нему доступ как 1

 kwargs['text']
 

Но, если пользователь не передает аргумент text , строка выше (попытка доступа к ключу text ) вызовет a KeyError , потому что этот ключ не будет существовать. Чтобы решить эту проблему, вы можете использовать dictionary.get(key, default) метод:

 self.text = kwargs.get('text', 'X')
 

который вместо создания исключения вернет значение по умолчанию.


1: Это синтаксис для получения значения, соответствующего ключу в словаре. Это вызовет ошибку, если ключ не существует в словаре.

Комментарии:

1. Более простой способ, если у вас есть значение по умолчанию: self.text = kwargs.get('text', 'X') .

2. @glglgl вы правы. Я не заметил, что в вопросе OP было значение по умолчанию. Отредактировано.

Ответ №2:

 def __init__(self, **kwargs): # kwargs is a dict containing text
    '''
    Constructor
    '''
    super(spot,self).__init__(**kwargs)
    self.ismine=False
    self.text=kwargs['text'] # you need to assign it here
 

Комментарии:

1. @surpavan при вызове функции с аргументами и / или ключевыми словами. Аргументы превращаются в список, а аргументы ключевого слова — в dict, когда вы выполняете *args и **kwargs соответственно. Таким образом, вы можете использовать их как таковые.

Ответ №3:

Другие ответы верны в общем смысле для Python, но они не объясняют, что происходит конкретно с Kivy.

text является a StringProperty для Button класса. Это означает, что вам не нужно присваивать значение в вашем конструкторе, пока вы вызываете конструктор суперкласса, потому что присвоение свойствам Kivy автоматически обрабатывается Kivy.

Например:

 In [1]: from kivy.uix.button import Button

In [2]: class TestButton(Button):
   ...:     def __init__(self, **kwargs):
   ...:         super(TestButton, self).__init__(**kwargs)
   ...:         

In [3]: test = TestButton(text='hi')

In [4]: test.text
Out[4]: 'hi'
 

Вы также можете сделать это со своими собственными свойствами:

 In [1]: from kivy.uix.widget import Widget

In [2]: from kivy.properties import StringProperty, BooleanProperty, NumericProperty

In [3]: class TestWidget(Widget):
   ...:     name = StringProperty()
   ...:     num = NumericProperty()
   ...:     active = BooleanProperty()
   ...:     

In [4]: test = TestWidget(name='testing', num=12, active=True)

In [5]: test.name, test.num, test.active
Out[5]: ('testing', 12, True)
 

(Помните, конечно, что без конструктора автоматически будет вызван конструктор суперкласса.)

Для получения дополнительной информации ознакомьтесь с разделом Свойств документации Kivy. Вы также можете найти раздел событий полезным.

Вы можете установить значения по умолчанию, если вы создали свойство самостоятельно, например:

 class TestWidget(Widget):
    prop = StringProperty('default text')
 

Для унаследованного свойства (например Button text ):

 class TestButton(Button):
    def __init__(self, **kwargs):
        kwargs.setdefault('text', 'default text')
        super(TestButton, self).__init__(**kwargs)
 

Комментарии:

1. Это не работает для меня. Значения по умолчанию для новых свойств отсутствуют для метода инициализации моих пользовательских виджетов. Например, для свойства ListProperty возвращается [], а не определенное значение по умолчанию.

2. @wackazong Они должны быть. Обратите внимание, что установка значения в kv — это не то же самое, что установка значения по умолчанию.

3. Ах, это была путаница. Просто для записи, если вам нужно получить значение файла KV, вам нужен метод отложенного инициализации, как описано здесь: groups.google.com/d/msg/kivy-users/LuiOykPGcpo/PbMCrYbddKMJ