Eigene Klasse als Liste

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Popkultur
User
Beiträge: 30
Registriert: Donnerstag 20. Oktober 2016, 16:46

Code: Alles auswählen

class TokenHolder():
    def __init__(self):
        self.id = defaultdict(int)
        self.text_id = defaultdict(int)
        self.token = defaultdict(str)
        self.timestamp = defaultdict(int)
        self.source = defaultdict(str)

tokens = [TokenHolder()]
for i in range(len(t)):
            tokens.id = self.token_i
            tokens.text_id = dataset['id']
            tokens.token = t[i]
            tokens.timestamp = dataset['timestamp']
            tokens.source = dataset['source']
Hallo!
Seht ihr worauf ich hinaus will? Ich will eine Liste mit eigener Klasse. Wie geh ich das an? Später soll die Klasse Funktionen bekommen, um zum Beispiel die Liste nach dem timestamp zu sortieren. Wie mach ich das? Oder ist dieser Ansatz grundlegend verkehrt? Danke für Hilfe.
BlackJack

@Popkultur: Also ich verstehe daraus jetzt nicht wirklich was Du willst, das sieht alles ein bisschen verquer aus. Zeile 13 bereitet mir zum Beispiel leichte Kopfschmerzen weil hier das `Tokeholder`-Exemplar selbst als Attribut auf, äh ja was eigentlich(?) gesetzt wird. Wobei ich da auch bei der Definition als ``defaultdict(str)`` schon glaube das Du das nicht ernst meinst. Was soll denn bei diesen ganzen `defaultdict`\s eigentlich gespeichert werden?

Versuch mal das Problem zu beschreiben, und zwar ohne schon eine Lösung, wirklich nur das Problem welches gelöst werden soll.

``for i in range(len(something)):`` ist übrigens auch ein Warnzeichen. So etwas ist in Python nur ganz selten wirklich das was man schreiben will.
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Du kannst eine Unterklasse von "list" erstellen.
So zum Beispiel:

Code: Alles auswählen

#python3
class Token():
    def __init__(self, id, text):
        self.id   = id
        self.text = text
    def __str__(self):
        return "Token({},{})".format(self.id, self.text)
    def __repr__(self):
        return "Token({},{})".format(self.id, self.text)

class TokenList(list):
    def sortbyid(self):
        self.sort(key=lambda token: token.id)
    def sortbyname(self):
        self.sort(key=lambda token: token.text)

tokens = TokenList()
tokens.append(Token(1, "hallo"))
tokens.append(Token(3, "ade"))
tokens.append(Token(2, "wiedersehen"))
tokens.append(Token(4, "bye"))

print(tokens)

tokens.sortbyid()
print(tokens)

tokens.sortbyname()
print(tokens)
Popkultur
User
Beiträge: 30
Registriert: Donnerstag 20. Oktober 2016, 16:46

Danke, das isses!
BlackJack

Würde ich nur machen wenn es wirklich eine Liste ist, also wenn tatsächlich alles was man mit einer Liste machen kann, auch mit der abgeleiteten Klasse Sinn macht *und* dann muss man natürlich noch darauf achten was zum Beispiel bei Slicing passiert. Wenn man das nicht selbst explizit überschreibt, dann kommen dabei ja wieder normale `list`-Objekte heraus. In der Regel erwartet man da aber Exemplare vom abgeleiteten Typ.

@heiner88: Die `__str__()`-Methode war unnötige Tipparbeit weil die Standardimplementierung schon auf `__repr__()` zurück greift. Selbst wenn sie das nicht täte sollte man die andere Methode nicht kopieren sondern einfach den Namen zuweisen:

Code: Alles auswählen

class Spam(object):
    # ...
    def __repr__(self):
        return '…'

    __str__ = __repr__
Aber wie gesagt, das ist sowieso schon „Default“.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

oder man spart sich die ganze Klasse und nimmt einfach ein namedtuple, dann kann man auch ganz einfach nach Attributen sortieren:

Code: Alles auswählen

from collections import namedtuple
Token = namedtuple('Token', 'id,text')

tokens = [
    Token(1, "hallo"),
    Token(3, "ade"),
    Token(2, "wiedersehen"),
    Token(4, "bye"),
]
 
tokens.sort(key=Token.text.fget)
print(tokens)
Antworten