Ошибка TypeError: refresh_data() takes 1 positional argument but 2 were given
У меня есть класс для динамического отображения графиков, написанный с использованием kivy:
class Graph(FloatLayout):
def __init__(self, root, name, x, y, height, width, time, graph_update_freq, data_update_freq, data_queue):
self.root = root
self.name = name
self.x = x
self.y = y
self.height = height
self.width = width
self.time = time
self.graph_update_freq = graph_update_freq
self.data_update_freq = data_update_freq
self.data_queue = data_queue
self.exist = True
self.step = int((self.width - 40) * data_update_freq / self.time)
self.len_graph_buf = int(self.time / data_update_freq)
self.deviation = int(((self.width - 40) - ((self.len_graph_buf - 1) * self.step)) / 2)
self.current_value = 0
self.previous_value = 0
self.graph_queue = []
for i in range(0, self.len_graph_buf):
self.graph_queue.append(0)
def start_read_data(self):
self.do_asyncio()
def do_asyncio(self):
Clock.schedule_once(self.refresh_data, 0.005)
def refresh_data(self):
if self.exist:
self.canvas.clear()
Builder.load_string('''
canvas:
Color:
rgba: 1, .1, .1, .9
Line:
points: 20 + self.deviation, 20, self.width - 20 - self.deviation, 20
width: 0.5
Color:
rgba: 69, 40, 66, 0.12
Line:
points: 20 + self.deviation, self.height - 20, self.width - 20 - self.deviation, self.height - 20
width: 0.5
Color:
rgba: 69, 40, 66, 0.12
Line:
points: 20 + self.deviation, self.height / 2, self.width - 20 - self.deviation, self.height / 2
width: 0.5
Line:
points: 20 + self.deviation, self.height - (self.height / 2 + 20) / 2,
self.width - 20 - self.deviation, self.height - (self.height / 2 + 20) / 2
width: 0.5
Color:
rgba: 69, 40, 66, 0.12
Line:
points: 20 + self.deviation, 10, 20 + self.deviation, self.height - 10
width: 0.5
Line:
points: self.width - 20 - self.deviation, 10,
self.width - 20 - self.deviation, self.height - 10
width: 0.5
Line:
points: 20 + self.deviation, self.height / 2,
self.width - 20 - self.deviation, self.height / 2
width: 0.5
''')
# TODO: масштаб
while not len(self.data_queue) == 0:
self.graph_queue.append(self.data_queue.pop(0) * int(self.height / 2 - 10))
self.graph_queue.pop(0)
j = len(self.graph_queue) - 1
self.current_value = self.graph_queue[j]
i = 0
maxx = 1e-7
for g in self.graph_queue:
if abs(g) > maxx:
maxx = abs(g)
mScale = (int(self.height / 2) - 20) / maxx
for j in range(self.len_graph_buf - 2, -1, -1):
self.previous_value = self.current_value
self.current_value = self.graph_queue[j]
self.l = Line(points=(i + 20 + self.deviation, int(-self.previous_value * self.mScale) + int(self.height / 2),
i + self.step + 20 + self.deviation, int(-self.current_value * self.mScale) + int(self.height / 2)),
fill='red') # ???
self.canvas.add(self.l)
i += self.step
Clock.schedule_once(self.refresh_data, self.graph_update_freq)
def remove(self):
self.exist = False
self.root.destroy()
при запуске файла main, который ссылается на вышенаписанный класс возникает ошибка: TypeError: refresh_data() takes 1 positional argument but 2 were given. Насколько я знаю, такая ошибка обычно появляется, когда в аргументах функции класса забывают указать self, но у функции refresh_data() он есть, в качестве единственного аргумента. Подозреваю, что проблема в данной строке: Clock.schedule_once(self.refresh_data, 0.005) так как в документации kivy.clock нет ни одного примера, где бы первый аргумент (выполняемая функция) указывалась после self. но если убрать self, среда тут же просит его вернуть из-за явной ошибки. Заранее спасибо за помощь
Ответы (2 шт):
В документации вижу, что Clock.schedule_once принимает функцию с одним аргументом dt.
Ваша refresh_data никакого аргумента dt не ожидает, поэтому и ошибка. Решается вполне очевидным способом с помощью лямбды. Этот способ рекомендует и документация:
Conversely, if you want to schedule a function that doesn’t accept the dt argument, you can use a lambda expression to write a short function that does accept dt
То есть вам нужно заменить строчку
Clock.schedule_once(self.refresh_data, self.graph_update_freq)
на такое:
Clock.schedule_once(lambda dt: self.refresh_data(), self.graph_update_freq)
PS: Кстати, вот в этом утверждении:
TypeError: refresh_data() takes 1 positional argument but 2 were given. Насколько я знаю, такая ошибка обычно появляется, когда в аргументах функции класса забывают указать self
вы немножко не правы. Если вы методе забудете self, то получите ошибку takes 0 positional arguments but 1 was given - то есть в описании функции 0 аргументов, но реально был передан неожиданный 1 аргумент self.
У вас же takes 1 positional argument but 2 were given - то есть 1 аргумент (self) есть в описании функции, но в реальности в функцию было передано два аргумента (один - self, и один - dt, который в вашу функцию попытался передать Clock).
Вместо
def refresh_data(self):примените
def refresh_data(self, dt):dt- это параметр, который заполняется функциейschedule_once()(реальное время между планированием и спуском).Вы можете затем использовать это значение или нет, но без этого параметра вы усложняете себе жизнь.
Вы вызываете функцию
schedule_once()дважды в вашем коде, пытая запланировать запуск того же метода —refresh_data().Это бы было в порядке, когда бы вы не планировали запуск этого метода из него самого, т.е. из метода
refresh_data()(бесконечный цикл). Я не знаю, что вы хотели этим достичь, но удалите этот вызов.