• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wywołanie klasy od nowa powoduje podwajanie się zapisanych w niej danych.

Cloud VPS
0 głosów
677 wizyt
pytanie zadane 20 stycznia 2019 w Python przez CP733 Początkujący (390 p.)

Witam. Nie mogę sobie poradzić z pewnym napotkanym problemem, otóż korzystam z discord.py i mam klasę w osobnym pliku, która zbiera dane ze strony najpierw wstrzykuje w tablice potem mam po prostu zmienną msg, do której są przez pętle dołączane kolejne stringi wszystko działa tak jak powinno, po wpisaniu określonej komendy wywoływana jest klasa i wysyłany jest zwrot z jednej z funkcji tej klasy na kanał. Problem się jednak pojawia, gdy chcę ponownie wpisać tę komendę, wszystko się podwaja. Zmienna msg wypluwa dwa razy to samo, i tak samo dzieje się z żądaniem do ów strony z której pobierane są dane, to żądanie po prostu się podwaja. Myślę, że chodzi o to, że mam tam tablice data i gdy raz wpisze komendę to ona zostanie uzupełniona i gdy drugi raz wpiszę komendę to ona znowu dostaje dawkę danych przez co siedzą tam dane z poprzedniego zainicjowania komendy i z drugiego, dokładnie tak jakbym używał pętli. Pytanie dlaczego tak się dzieje, jak mam oczyścić tę tablicę zanim wykonam następną komendę. Próbowałem różnymi metodami, jakoś tą tablicę wyczyścić jednak nic nie przynosi oczekiwanego skutku.
 

@client.command(name='komenda')
async def earning(ctx, arg):
    ge = GroupEarnings('nazwa grupy')
    await ctx.send(ge.msg)

tak wygląda ta komenda

komentarz 20 stycznia 2019 przez RafalS VIP (122,820 p.)
Wrzuć więcej kodu. Określenia opisujące kod są niejasne i trochę chaotyczne.
komentarz 20 stycznia 2019 przez CP733 Początkujący (390 p.)
Jasne. Już wrzucam.

2 odpowiedzi

+1 głos
odpowiedź 20 stycznia 2019 przez RafalS VIP (122,820 p.)
wybrane 20 stycznia 2019 przez CP733
 
Najlepsza

Przykład podawany nawet w dokumentacji jako "gotcha" :P

class A:
    lista = []

a = A()
# is - sprawdza czy to dokladnie ten sam obiekt
# == porownuje czy obiekty maja rowne wartosci
assert a.lista is A.lista
a.lista.append(1)
A.lista.append(2)
assert a.lista == A.lista and a.lista == [1, 2]
a.lista = []
assert A.lista == [1, 2]
assert a.lista is not A.lista

Twój atrybut data jest tą samą listą dla każdego nowego obiektu. Poprawnie powinieneś zainicjować go w __init__ jako self.data = []

class GroupEarnings:
    group_name = ''
    def __init__(self, name):
        self.group_name = name

To nie ma sensu. Iniciujesz group_name jako statyczny atrybut, czyli taki, który należy do klasy a nie obiektu. Po czym w inicie tworzysz inny atrybut o tej samej nazwie - self.group_name a z GroupEarnings.group_name nigdzie nie korzystasz.

Z uwag to przede wszystkim bardzo dziwne nazewnictwo. Metoda zaczynająca się od get (get_group_earnings) nic nie zwraca, a set_group_earnings zwraca :D. Powinno być na odwrót.

Cała logika wywołana w inicie to też chyba nie najlepszy pomysł. Z zewnątrz nie widać co klasa robi:

ge = GroupEarnings('nazwa grupy')
await ctx.send(ge.msg)

Korzystanie z tej klasy polega na stworzeniu obiektu i pobraniu atrybutu msg? Którego tak na marginesie nazwa też nie jest najlepsza :P.

for x in self.data:

czym jest data, czym jest x. Nie wiem, bo nazwa tego nie mówi.

for i in offers

czemu nie for offer in offers?

self.data.append({'uid': row['value'], 'name': name.split(" (")[0]})

Zamiast robic listę słowników polecam stworzyć na to prostą klase, albo jeszcze lepiej skorzystac z collections.namedtuple:

from collections import namedtuple
Wpis = namedtuple("Wpis", "uid name")
....
     self.data.append(Wpis(uid=row['value'], name=name.split(" (")[0]))
iterate += 20

? czemu ta zmienna nazywa sie jakby byla iteratorem pętli a wyglada jakby cos hurtowo liczyła.

Sporo break w pętli nie ułatwia śledzenia jej przebiegu.

komentarz 20 stycznia 2019 przez CP733 Początkujący (390 p.)
No masz rację co do nazewnictwa to lekko zbłądziłem przez to całe kombinatorstwo wynikające z prób naprawienia tego dublowania. Tak samo ge.msg na początku nie było i logiki w inicie. Dzięki za rady, na pewno skorzystam.
0 głosów
odpowiedź 20 stycznia 2019 przez CP733 Początkujący (390 p.)
from bs4 import BeautifulSoup
from datetime import datetime, timedelta
import requests
import re


class GroupEarnings:
    url = 'strona'
    jar = requests.cookies.RequestsCookieJar()
    #tutaj ustawiają się oczywiście ciasteczka
    #tutaj ustawiają się oczywiście ciasteczka
    #tutaj ustawiają się oczywiście ciasteczka
    data = []
    group_name = ''
    msg = ''

    def __init__(self, name):
        r = requests.get(self.url, cookies=self.jar)
        self.group_name = name
        self.soup = BeautifulSoup(r.text, 'html.parser')
        self.set_group_data(name)
        self.get_group_earnings()

    def set_group_data(self, arg):
        group = self.soup.find('optgroup', attrs={'label': arg})
        rows = group.find_all('option')
        for row in rows:
            name = row.get_text()
            self.data.append({'uid': row['value'], 'name': name.split(" (")[0]})

    def set_group_earnings(self, days):
        group_earnings = []
        for x in self.data:
            amount = 0
            iterate = 0
            end_iterate = False
            while iterate < 1000:

                if end_iterate:
                    break

                url = "strona".format(x['uid'], iterate)
                r = requests.get(url, cookies=self.jar)
                soup = BeautifulSoup(r.text, 'html.parser')

                if iterate and not soup.find('li', {'class': 'next'}):
                    break

                offers = soup.find_all('td')

                if not offers:
                    break

                for i in offers:
                    matches = re.findall(r"(?<=om\)\$)(.*?)(?= \-)", i.get_text())
                    if matches:
                        date_matches = re.findall(r"(?<=desc\">)(.*?)(?=<\/span><\/td>)", str(i))
                        if 'dziś' in date_matches[0]:
                            offer_date = datetime.strptime(date_matches[0].split(' ')[1], '%H:%M')
                            offer_date = offer_date.replace(year=datetime.now().year, month=datetime.now().month, day=datetime.now().day)
                        elif 'wczoraj' in date_matches[0]:
                            offer_date = datetime.strptime(date_matches[0].split(' ')[1], '%H:%M')
                            offer_date = offer_date.replace(year=datetime.now().year, month=datetime.now().month, day=datetime.now().day-1)
                        else:
                            offer_date = datetime.strptime(date_matches[0], '%d-%m-%y %H:%M')

                        end_date = datetime.now().replace(hour=18, minute=00, second=00, microsecond=00) - timedelta(days=days)

                        if offer_date < end_date:
                            end_iterate = True
                            break
                        else:
                            amount += int(matches[0])

                iterate += 20

            group_earnings.append({'name': x['name'], 'amount': amount})

        return group_earnings

    def get_group_earnings(self, days=7):
        self.msg = ' **' + self.group_name + '**: '
        group_earnings = self.set_group_earnings(days)
        count = 0
        for x in group_earnings:
            amount = x['amount']
            name = x['name']
            self.msg += "\n**" + name + '** **$' + str(amount) + '**  **$' + str(round(amount / 2)) + '**  **$' + str(round(amount * 0.20)) + '** **$' + str(round(amount * 0.30)) + '** '
            count += 1

Również będę wdzięczny za jakiekolwiek rady dotyczące tego kodu.

Podobne pytania

0 głosów
1 odpowiedź 603 wizyt
pytanie zadane 26 stycznia 2021 w Python przez Stefan Marzec Użytkownik (710 p.)
0 głosów
1 odpowiedź 319 wizyt
pytanie zadane 23 sierpnia 2020 w Python przez Szymi12 Użytkownik (630 p.)
0 głosów
1 odpowiedź 530 wizyt

93,454 zapytań

142,449 odpowiedzi

322,718 komentarzy

62,833 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...