Geschweifte Klammern Ausgabe bei __repr__

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.
Sirius3
User
Beiträge: 17843
Registriert: Sonntag 21. Oktober 2012, 17:20

Jetzt solltest Du Dir nochmal ganz genau anschauen, welche Argumente welchem __init__-Aufruf übergeben werden. Du hast zwei Fehler, die sich gegenseitig aufheben.
martin2p
User
Beiträge: 15
Registriert: Sonntag 22. Oktober 2023, 21:40

Meinst du hier?:

Code: Alles auswählen

school = School("Pleissa", "high", 100)
print(school)
print(school.name)
print(school.level)
school.number_of_Students = 200
print(school.number_of_Students)
Dass quasi die 200 nicht ausgegeben wird sondern 100 bleibt?
Benutzeravatar
__blackjack__
User
Beiträge: 13264
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@martin2p: Da bleibt nichts bei 100. Und bei `School` ist das auch noch richtig. Bei den beiden abgeleiteten Klassen ist es falsch.

Im Grunde würde ich es auch als falsch ansehen das man bei `PrimarySchool` immer ein "primary" und bei `HighSchool` immer ein "high" übergeben muss. Das ist ja offensichtlich redundant und sollte schon im Datentyp enthalten sein und nur bei der allgemeinen `School`-Klasse übergeben werden müssen, weil es dort eben noch nicht aus dem Datentyp klar ist um welche Art von Schule es sich handelt.
Please call it what it is: copyright infringement, not piracy. Piracy takes place in international waters, and involves one or more of theft, murder, rape and kidnapping. Making an unauthorized copy of a piece of software is not piracy, it is an infringement of a government-granted monopoly.
martin2p
User
Beiträge: 15
Registriert: Sonntag 22. Oktober 2023, 21:40

Ihr meint also, dass man bei diesen beiden:

Code: Alles auswählen

school = PrimarySchool("Grundschule", "primary", 300, "Pickup Allowed")
print(school)

school = HighSchool("Gymnasium", "High", 500, ["Tennis", "Basketball"])
print(school)

quasi die Bezeichnung der Klasse in die jeweilige def __init__() übergeben soll?

Code: Alles auswählen

class PrimarySchool(School):
    def __init__(self, level, name, number_of_Students, pickup_policy):
        super().__init__(level, name, number_of_Students)
        self.pickup_policy = pickup_policy

class HighSchool(School):
    def __init__(self, level, name, number_of_Students, sports_teams):
        super().__init__(level, name, number_of_Students)
        self.sports_teams = sports_teams
Ich hab versucht im jeweiligen Konstruktor das level = high oder primary zu setzen, dann kommt er jedoch mit den default Argumenten wie name, etc. nicht mehr klar.
Benutzeravatar
__blackjack__
User
Beiträge: 13264
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@martin2p: Weder `PrimarySchool.__init__()` noch `HighSchool.__init__()` sollte man `level` übergeben müssen. Das macht keinen Sinn etwas übergeben zu müssen was bei jedem Aufruf den jeweils gleichen Wert haben muss. Denn ein ``school = PrimarySchool("high", "Van Rossum Elementary", 42, "pickup allowed")`` wäre *falsch* weil eine Grundschule keine Highschool ist. Und *das* das eine Grundschule ist, wird ja schon dadurch klar, dass man `PrimarySchool` verwendet. Wenn man eine Highschool haben wollte, würde man ja die `HighSchool`-Klasse verwenden. Also *muss* man bei `PrimarySchool` als `level` *immer* "primary" übergeben und bei `HighSchool` *immer* "high". Das macht keinen Sinn. Dieses Wissen sollte in der Klasse selbst stecken.
Please call it what it is: copyright infringement, not piracy. Piracy takes place in international waters, and involves one or more of theft, murder, rape and kidnapping. Making an unauthorized copy of a piece of software is not piracy, it is an infringement of a government-granted monopoly.
Benutzeravatar
snafu
User
Beiträge: 6752
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Analog zu "primary" würde ich ja "secondary" nehmen. Diese Einteilung der Schulformen ist im englischsprachigen Raum geläufig. Und im Deutschen gibt es ja auch die Sekundärstufe.

Wenn du jetzt noch den mehrfach geäußerten Vorschlag der Vorposter umsetzt, dann hast du (hoffentlich) ein bisschen mehr von der Funktionsweise einer Basisklasse beim Vererben verstanden. Mach dir einfach mal klar, dass eine abgeleitete Klasse nicht zwingend jedes Argument der Basisklasse in ihrer Signatur enthalten muss. Manchmal werden Argumente auch nur intern verwendet, um die Basisklasse sinnvoll initialisieren zu können.
martin2p
User
Beiträge: 15
Registriert: Sonntag 22. Oktober 2023, 21:40

Ich verstehe worauf ihr hinaus wollt, aber ich habe keine Ahnung wie ich das in den Code einbauen soll. Dass quasi der Klassenname als Referenz für das Level einzusetzen ist :(

Die Subklassen PrimarySchool und Highschool greifen ja immer auf den __str__ Befehl der Elternklasse School zurück, also auf diesen Ausdruck:

Code: Alles auswählen

def __str__(self):
        return f"A {self.level} school named {self.name} with {self.number_of_Students} students. "
Könnt ihr mir bitte zeigen wie ich das schreiben muss? Ich bekomme es einfach nicht hin...

Code: Alles auswählen

class School:
    def __init__(self, level, name, number_of_Students):
        self.name = name
        self.level = level
        self.number_of_Students = number_of_Students

    def __str__(self):
        return f"A {self.level} school named {self.name} with {self.number_of_Students} students."



class PrimarySchool(School):
    def __init__(self, name, number_of_Students, pickup_policy):
        super().__init__(name, number_of_Students)
        self.pickup_policy = pickup_policy

    def __str__(self):
        return f"{super().__str__()} The pickup policy is {self.pickup_policy}."



class SecondarySchool(School):
    def __init__(self, name, number_of_Students, sports_teams):
        super().__init__(name, number_of_Students)
        self.sports_teams = sports_teams

    def __str__(self):
        return f"{super().__str__()} SportsTeams: {self.sports_teams}."


######################################

school = School("Pleissa", "Highschool", 100)
print(school)
print(school.name)
print(school.level)
school.number_of_Students = 200
print(school.number_of_Students)

school = PrimarySchool("Grundschule", 300, "Pickup Allowed")
print(school)

school = SecondarySchool("Gymnasium", 500, ["Tennis", "Basketball"])
print(school)
narpfel
User
Beiträge: 646
Registriert: Freitag 20. Oktober 2017, 16:10

@martin2p: Die Elternklasse erwartet, dass ein `level` an `__init__` übergeben wird. Also musst du beim Aufruf von `super().__init__` in den Kindklassen ein `level` übergeben.
martin2p
User
Beiträge: 15
Registriert: Sonntag 22. Oktober 2023, 21:40

Über self.level oder level="Primary" ?

Ich habe verschiedene Varianten durchprobiert und erhalte nur Errors
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Schau dir die Parameter von school an, und was du daran übergibst in deinen abgeleiteten Klassen. Im super()-Aufruf.
narpfel
User
Beiträge: 646
Registriert: Freitag 20. Oktober 2017, 16:10

martin2p hat geschrieben: Mittwoch 25. Oktober 2023, 18:59 Ich habe verschiedene Varianten durchprobiert und erhalte nur Errors
Die Fehlermeldungen sind dazu da, dir zu helfen. Fehlermeldungen zu lesen und zu verstehen ist eins der wichtigsten Dinge, die man lernen muss, weil Fehlermeldungen der Weg sind, mit der dir Python sagt, was du wo falsch gemacht hast. Also musst du die Fehlermeldungen entweder selbst lesen, oder (zusammen mit dem passenden Code) hier zeigen, damit wir Hinweise geben können, die dir helfen, die Fehlermeldungen zu verstehen.

Und zu deiner Frage: Übergeben ist ein fester Begriff, der immer das gleiche bedeutet. Man übergibt Parameter an Funktionen. Eine Zuweisung ist keine Übergabe.
martin2p
User
Beiträge: 15
Registriert: Sonntag 22. Oktober 2023, 21:40

So ich habs nun endlich ... mit euch möchte ich nie Rätselraten spielen :lol:

Code: Alles auswählen

class School:
    def __init__(self, level, name, number_of_Students):
        self.name = name
        self.level = level
        self.number_of_Students = number_of_Students

    def __str__(self):
        return f"A {self.level} school named {self.name} with {self.number_of_Students} students."


class PrimarySchool(School):
    def __init__(self, name, number_of_Students, pickup_policy):
        super().__init__("Primary", name, number_of_Students)
        self.pickup_policy = pickup_policy

    def __str__(self):
        return f"{super().__str__()} The pickup policy is {self.pickup_policy}."


class SecondarySchool(School):
    def __init__(self, name, number_of_Students, sports_teams):
        super().__init__("Secondary", name, number_of_Students)
        self.sports_teams = sports_teams

    def __str__(self):
        return f"{super().__str__()} SportsTeams: {self.sports_teams}."


######################################

school = School("Highschool", "Pleissa", 100)
print(school)
print(school.name)
print(school.level)
school.number_of_Students = 200
print(school.number_of_Students)

school = PrimarySchool("Testschule", 300, "Pickup Allowed")
print(school)


school = SecondarySchool("Testschule2", 500, ["Tennis", "Basketball"])
print(school)

Code: Alles auswählen

A Highschool school named Pleissa with 100 students.
Pleissa
Highschool
200
A Primary school named Testschule with 300 students. The pickup policy is Pickup Allowed.
A Secondary school named Testschule2 with 500 students. SportsTeams: ['Tennis', 'Basketball'].
Ist das nun in Ordnung so????
Benutzeravatar
snafu
User
Beiträge: 6752
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich kenne die Aufgabenstellung im Original nicht, aber der direkte Aufruf von School() sieht in diesem Zusammenhang irgendwie komisch aus, zumindest wenn da "Highschool school" rauskommt. Da fährt man besser, wenn man das Level optional macht, also mit None vorbelegt und beim Erzeugen des Textes dann eine Sonderbehandlung für None einbaut.

Und die Sport-Teams könnte man auch mit ", ".join() anzeigen lassen.
Benutzeravatar
__blackjack__
User
Beiträge: 13264
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wegen dem leichten Unglauben, dass man da so viel Code ”wiederholen” muss, hier mal das gleiche Programm in der Programmiersprache in der mein erster Kontakt mit Objektorientierung war: Turbo Pascal. Da muss man nicht nur Getter/Setter schreiben, weil es keine Properties gibt, sondern sich auch noch selber um die Speicherverwaltung kümmern, und die Klassen zum entsprechenden Untertyp casten weil man nicht einfach so alle Methoden aufrufen kann, sondern nur solche die zur Typdeklaration passen:

Code: Alles auswählen

program Schools;

type
  PSchool = ^TSchool;
  TSchool = object
    private
      name: String;
      level: String;
      numberOfStudents: Word;
    public
      constructor Init(n: String; lvl: String; nStudents: Word);
      function GetName: String;
      function GetLevel: String;
      function GetNumberOfStudents: Word;
      procedure SetNumberOfStudents(n: Word);
      function ToString: String; virtual;
  end;
  PPrimarySchool = ^TPrimarySchool;
  TPrimarySchool = object(TSchool)
    private
      pickupPolicy: String;
    public
      constructor Init(n: String; nStudents: Word; pPolicy: String);
      function GetPickupPolicy: String;
      function ToString: String; virtual;
  end;
  PHighschool = ^THighschool;
  THighschool = object(TSchool)
    private
      sportsTeams: String;
    public
      constructor Init(n: String; nStudents: Word; teams: String);
      function GetSportsTeams: String;
      function ToString: String; virtual;
  end;

var
  school: ^TSchool;

constructor TSchool.Init(n: String; lvl: String; nStudents: Word);
begin
  name := n;
  level := lvl;
  numberOfStudents := nStudents;
end;

function TSchool.GetName: String;
begin
  GetName := name;
end;

function TSchool.GetLevel: String;
begin
  GetLevel := level;
end;

function TSchool.GetNumberOfStudents: Word;
begin
  GetNumberOfStudents := numberOfStudents;
end;

procedure TSchool.SetNumberOfStudents(n: Word);
begin
  numberOfStudents := n;
end;

function TSchool.ToString: String;
var
  s: String;
begin
  Str(GetNumberOfStudents, s);
  ToString := 'A ' + GetLevel + ' school named ' + GetName + ' with ' + s
              + ' students.';
end;

constructor TPrimarySchool.Init(n: String; nStudents: Word; pPolicy: String);
begin
  inherited Init(n, 'primary', nStudents);
  pickupPolicy := pPolicy;
end;

function TPrimarySchool.GetPickupPolicy: String;
begin
  GetPickupPolicy := pickupPolicy;
end;

function TPrimarySchool.ToString: String;
begin
  ToString := inherited ToString + ' The pickup policy is ' + GetPickupPolicy
              + '.';
end;

constructor THighschool.Init(n: String; nStudents: Word; teams: String);
begin
  inherited Init(n, 'high', nStudents);
  sportsTeams := teams;
end;

function THighschool.GetSportsTeams: String;
begin
  GetSportsTeams := sportsTeams;
end;

function THighschool.ToString: String;
begin
  ToString := inherited ToString + ' Sports teams: ' + GetSportsTeams + '.';
end;

begin
  school := New(PSchool, Init('Pleissa', 'high', 100));
  WriteLn(school^.ToString);
  WriteLn(school^.GetName);
  WriteLn(school^.GetLevel);
  school^.SetNumberOfStudents(200);
  WriteLn(school^.GetNumberOfStudents);
  Dispose(school);

  school := New(PPrimarySchool, Init('Codecademy', 300, 'pickup allowed'));
  WriteLn(PPrimarySchool(school)^.GetPickupPolicy);
  WriteLn(school^.ToString);
  Dispose(school);

  school := New(PHighschool,
                Init('Rock''n''Roll High', 500, 'Tennis, Basketball'));
  WriteLn(PHighschool(school)^.GetSportsTeams);
  WriteLn(school^.ToString);
  Dispose(school);
end.
Die Sport-Teams habe ich hier mal als Zeichenkette umgesetzt, weil eine dynamische Datenstruktur das noch mal *deutlich* verlängert hätte, weil man die hätte selbst implementieren müssen, und die Klassen hätten dann noch einen Destruktor gebraucht um den Speicher *dafür* dann auch wieder freizugeben.
Please call it what it is: copyright infringement, not piracy. Piracy takes place in international waters, and involves one or more of theft, murder, rape and kidnapping. Making an unauthorized copy of a piece of software is not piracy, it is an infringement of a government-granted monopoly.
Antworten