String in Variable Umwandeln

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
Fiscek
User
Beiträge: 2
Registriert: Samstag 1. Januar 2022, 21:57

Code: Alles auswählen

class NPC:
    def __init__(self, name, alter, geschlecht):
        self.Name=name
        self.Alter=alter
        self.Geschlecht=geschlecht
        
        
class Beruf(NPC):
    def __init__(self, name, alter, geschlecht, beruf):
        if alter < 18:
            self.Beruf='Schüler'
        elif alter >= 18 and alter < 65:
            self.Beruf=beruf
        else:
            self.Beruf='Rentner'
        super().__init__(name, alter, geschlecht)


beruf1=Beruf('Micha', 24, 'Mann', 'Müller')
beruf2=Beruf('Laura', 28, 'Frau', 'Fischer')
beruf3=Beruf('Alexa', 12, 'Frau', 'Wache' )
beruf4=Beruf('Max', 66, 'Mann', 'Bauer')

def personendaten(x):
    print('Name des NPC ist: ' + str(x.Name))
    print('Alter des NPC beträgt: '+ str(x.Alter))
    print('Das Geschlecht des NPC ist: '+ str(x.Geschlecht))
    print('der Beruf ist: ' + str(x.Beruf))

for x in (beruf1, beruf2, beruf3, beruf4):
    personendaten(x)
    print('-------------------------------------')
Guten Abend alle zusammen. Ich bin neu bei Python und bis jetzt habe ich auch alle Probleme alleine gelöst. Leider steh ich jetzt vor einem großem Fragzeichen.
Ich möchte aus einer liste von Personen NPC's Konstruieren die Berufe haben. So wie der Code jetzt ist funktioniert er auch, aber ich würde ihn gerne modifizieren.
Ich hätte es gerne das alles automatisch abläuft auch die vergabe der Variable für die Klasse bzw. den Konstruktor.

Code: Alles auswählen

VariabbelListe=(beruf1, beruf2, ..... Beruf30)
Personendaten=((Max, 33, Mann, Händler))

    
    (VariabelListe)     (PersonendatenListe)
        |                			  |
        |              				  |
        v                 			 v                   
    Variable1=Beruf(name, alter, geschlecht, beruf)
Leider konnte mir auch Google nicht weiter helfen . Gibt es einen Weg wie man einen String, aus einer Liste, in eine Variable umwandeln kann?

Mit freundlichen Grüßen Fiscek
Benutzeravatar
sparrow
User
Beiträge: 4540
Registriert: Freitag 17. April 2009, 10:28

Ich verstehe deine Frage nicht ganz, aber ich vermute, du willst einfach die erstellten NPCs einfach in eine Liste tun.
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Man erzeugt keine Variablennamen, sondern benutzt passende Datenstrukturen, hier eine Liste.
Attribute schreibt man wie Variablennamen komplett klein.
Ich weiß nicht was NPC bedeutet. Benutze nie kryptische Abkürzungen. Die Klasse `Beruf` ist falsch. Ein Beruf hat keinen Namen und kein Alter. Was soll die Klasse denn machen?
Funktionen benennt man nach Tätigkeiten, `personendaten` ist aber keine. Statt Strings mit + zusammen zu setzen, benutzt man Formatstrings. x ist ein schlechter Variablennamen für eine Person.
imonbln
User
Beiträge: 191
Registriert: Freitag 3. Dezember 2021, 17:07

NPC soll vielleicht non-player character heißen. Die Fragestellung ist irgendwie wirr. Vielleicht meint er eine einfach For schleife oder ein getattr. Vermutlich hat aber Sirius3 recht.

Die Tipps von Sirus3 sind insgesamt alle richtig. Die Klasse Beruf, definitiv falsch, ein Beruf hat kein Alter und kein Geschlecht. Warum ist der Beruf kein Attribut des NPC? Außerdem sollte das Geschlecht kein String sein, hier würde sich ein Enum anbieten oder wenn man nur Mann und Frau haben will vielleicht auch ein bool, à la is_female = True. Ich glaube, ich würde es mit einem Enum machen und wenn schon mit Enums gearbeitet wird könnten die Berufe auch ein Enum sein und als Attribut von NPC gespeichert werden.

Dass beim Initialisieren von Beruf ein Beruf angeben werden muss, aber wenn die Person jünger als 18 oder älter als 65 ist, etwas anders eingetragen wird, ist für einen erfahrenen Entwickler unerwartet. Entweder der Initialisierung nimmt die Daten oder es sollte eine Exception geworfen werden, aber einfach etwas anderes zu machen ist schlechter Still.

Als Faustformel kannst du dir auch merken, wenn ein Attribut der Klasse genau so heißt wie die Klasse selbst, ist das oft ein Anzeichen, dass etwas mit den Klassen Design nicht stimmt.

Die Funktion Personendaten, sollte mindesten ein Class member sein, ich würde das wahrscheinlich in der __str__ Methode Implementieren dann kann im Programm einfach print(instance) geschrieben werden.
Außerdem empfehle ich dir innerhalb des Programms Englische Bezeichner zu wählen, im Rahmen von größeren Softwareprojekten, kannst du nicht davon ausgehen das jeder Deutsch versteht, daher lohnt es sich das gleich von Beginn „richtig“ zu machen.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Fiscek,

Bevor man NPCs in Klassen modelliert sollte man sich die Frage stellen: "Wie verhält sich Beruf zu NPC?". *Hat* ein NPC einen Beruf? Dann wäre der Beruf ein einfaches Klassenattribut der NPC Klasse:

Code: Alles auswählen

class NPC:
    def __init__(self, name, age, gender, profession):
        self.name = name
        self.age = age
        self.gender = gender
        self.profession = profession
Oder: *Ist* ein NPC ein Müller? *Ist* ein NPC ein Bauer? Dann wäre der Beruf eine Unterklasse (Spezialisierung) für einen NPC

Code: Alles auswählen

class NPC:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def __str__(self):
        return f"{self.__class__.__name__} {self.name}, is {self.gender.value} and {self.age} years old"

class Farmer(NPC):
    pass

class Miller(NPC):
    pass

class Student(NPC):
    pass
Ob die Formulierung mit *hat* oder *ist* besser passt, gibt also schon mal grob Aufschluss darüber, welche Art der Modellierung besser geeignet ist.
hat: Komposition (Eine Klasse *hat* ein Attribut)
ist: Vererbung (Eine Unterklasse *ist* eine Spezialisierung einer Basisklasse)

Manchmal lässt sich diese Frage leicht beantworten, manchmal weniger.
Eine Amsel *ist* ein Vogel.
Frau Müller *hat* einen Vogel, denn sie glaubt, sie *ist* eine Amsel, ... hää? :?

Im konkreten Fall, sind beide Ansätze denkbar.
Nehmen wir mal an der Beruf sei eine Form der Spezialisierung für NPCs. Schüler, Müller, Bauer sind spezielle NPCs.

Die Einstufung Student, Müller oder Rentner nach Alter, gehört dann auch nicht in die Klasse. Dies sollte vor der Instanziierung der Klasse entschieden werden. Bzw. es sollte schon in den Daten aus denen die Klassen generiert werden, festgelegt sein.

Angenommen die Daten liegen in einer Liste aus Tupeln, dann kann man daraus eine Liste von NPCs erzeugen:

Code: Alles auswählen

class Gender(Enum):
    FEMALE = "female"
    MALE = "male"

NPC_DATA = [
    (Farmer, "Max", 46, Gender.MALE),
    (Miller, "Mia", 45, Gender.FEMALE),
    (Student, "Susi", 17, Gender.FEMALE),
]

def make_npcs():
    return [profession(name, age, gender) for profession, name, age, gender in NPC_DATA]
Und ausgeben:

Code: Alles auswählen

def main():
    npcs = make_npcs()
    for npc in npcs:
        print(npc)
       
if __name__ == main():
    main()
    
"""
Farmer Max, is male and 46 years old
Miller Mia, is female and 45 years old
Student Susi, is female and 17 years old
"""
Ein paar Hintergrund-Informationen zur Frage "Was sind NPCs?":
https://www.youtube.com/watch?v=lbJ51AJ ... EnyUG8totf
Fiscek
User
Beiträge: 2
Registriert: Samstag 1. Januar 2022, 21:57

Danke erstmal für das viele feedback. tut mir leid falls ich mich schlecht ausgedrückt habe. in der Tat NPC soll Non-player Character bedeuten.
ich wollte durch die Klasse eine große Zahl an NPC vorbereiten um sie im weiter verlauf zu benutzen. mit dem automatisieren meinte ich, das ich selbst die Instanz vergabe automatisieren wollte.
ich habe es heute doch geschafft wie ich es mir in etwa vorstelle.

Code: Alles auswählen

class NPC:
    def __init__(self, name, age):
        self.name=name
        self.age=age




counter=0
counter_limit=4
while counter!=counter_limit:
    x='Max','Achim','Micha','Alex'
    y=22,45,56,12
    code=('''NPC'''+str(counter)+'''=NPC(x'''+str([counter])+''', y'''+str([counter])+''')''')
    exec(code)
    counter=counter+1
print(NPC0.name)
print(NPC0.age)
print(NPC1.name)
print(NPC1.age)
print(NPC2.name)
print(NPC2.age)
print(NPC3.name)
print(NPC3.age)
in diesem Beispiel arbeite ich mit zwei Listen. einmal x für meine Namensliste und y für meine Altersliste. Hier habe ich erstmal keine Liste mit Instanzen. im Beispiel wird nur eine neue Zahl durch den counter
an NPC gehängt. counter_limit ist im normallfall die länge der kleinsten Liste. ich hoffe das ist so verständlich. Ich werde wohl doch lieber manuell alles eingeben. ist wohl das beste bis ich das Thema Klassen und Vererbungen besser verstehe.

Danke Sirius3 und imonbln ich habe eure Tipps umgesetzt. Ist das ungefähr was Ihr meintet? Das Beispiel mit Enum muss ich mir noch genauer angucken.

Code: Alles auswählen

class NPC:
    def __init__(self, name, age, sex, job):
        self.name=name
        self.age=age
        self.sex=sex
        if age < 18:
            assert job=='Schüler',('Error: Der Beruf für diese Altersgruppe '
                                   'ist auf Schüler eingeschränkt!')
            self.job=job
        elif age > 18 and age < 65:
            assert job!='Schüler',('Error: Dieser Beruf ist für diese'
                                   ' Altersgruppe nicht verfügbar!')
            assert job!='Rentner',('Error: Dieser Beruf ist für diese'
                                   ' Altersgruppe nicht verfügbar!')
            self.job=job
        else:
            assert job=='Rentner',('Error: Der Beruf für diese Altersgruppe'
                                   ' ist auf Rentner eingeschränkt! ')
            self.job=job
        
    def output(self):
            print(f'Der Name des NPC lautet:    {self.name}')
            print(f'Das Alter des NPC beträgt:  {self.age}')
            print(f'Das Geschlecht des NPC ist: {self.sex}')
            print(f'Der Beruf des NPC ist:      {self.job}')
            print('------------------------------------')
            
            


NPC1=NPC('Micha', 24, 'Mann', 'Müller')
NPC2=NPC('Laura', 28, 'Frau', 'Fischer')
NPC3=NPC('Alexa', 12, 'Frau', 'Schüler')
NPC4=NPC('Max', 66, 'Mann', 'Rentner')

print(NPC1.output())
print(NPC2.output())
print(NPC3.output())
print(NPC4.output())
Ich hätte da noch eine Frage. Eigentlich hatte ich zuerst die __str__ Methode benutzt, dass hat aber zur einer Fehlermeldung geführt. Danach habe ich __str__ zu ausgabe geändert.
Anschließend habe ich gesehen das unter meinem print-Block ein None auftaucht. Die __str__ Methode kommt damit nicht klar. Meine frage wäre in dem fall woher kommt der
ausgegebene Wert None?

Die Ausgabe:

Code: Alles auswählen

Der Name des NPC lautet:    Max
Das Alter des NPC beträgt:  66
Das Geschlecht des NPC ist: Mann
Der Beruf des NPC ist:      Rentner
------------------------------------
None
Hallo rogerb,
leider hab ich deine Antwort zu spät gesehen. Danke für die Erklärung mit *ist* und *hat* sowas habe ich leider nicht in meinen Recherchen gesehen. Du hast auch recht ich muss mich erstmal mit
NPC besser befassen damit ich sie auch besser modellieren kann.

Mit freundlichen Grüßen
Fiscek
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du exec benutzt, machst du etwas falsch. Das ist eine Riesen Sixherheitslücke, und erzeugt konfusen Code.

Du musst dringend die Grundlagen zu Datenstrukturen, vor allem Listen & Wörterbüchern, durcharbeiten.
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Du benutzt eine while-Schleife, wo man eine for-Schleife benutzen sollte. `x` und `y` sind keine Listen, sondern Tuple, sind verwirrende Namen statt `names` oder `ages`, wobei man zusammengehörende Daten auch zusammen speichern solle. `exec` ist nichts was in einem sauberen Programm zu suchen hat. `code` ist sowas von unlesbar, wie kommt man auf die Idee, die Repräsentation einer Liste mit einem Element zu einem Indexzugriff zusammenzusetzen?

Code: Alles auswählen

class NonPlayerCharacter:
    def __init__(self, name, age):
        self.name=name
        self.age=age

CHARACTERS = [
    ('Max', 22),
    ('Achim', 45),
    ('Micha', 56),
    ('Alex', 12),
]

characters = []
for name, age in CHARACTERS:
    characters.append(NonPlayerCharacter(name, age))

for character in characters:
    print(character.name)
    print(character.age)
imonbln
User
Beiträge: 191
Registriert: Freitag 3. Dezember 2021, 17:07

Der Code ist schon viel besser als deine ersten versuche, das mit exec haben dir auch schon andere gesagt, daher beschränke ich mich mal auf deine NPC klasse. Die Output-Methode hat selbst schon des Print und gibt None zurück, sie daher nochmal in einen Print zu schreiben ist überflüssig wie du am None in deiner Ausgabe siehst.

Die Assertion in der init sind schonmal ein Schritt in die richtige Richtung, aber ich würde einfach ein ValueError werfen. Ansonsten wie schon gesagt das Geschlecht sollte ein bool oder Enum sein kein String. Aber alles in allen ist der Code schon besser geworden.

Hier mal eine leicht verbesserte Version, die Typehints in den Methoden, sollten dich nicht stören, die sind optional in Python helfen aber bei geeigneter IDE, besseren Code zu schreiben.

Code: Alles auswählen

import enum

@enum.unique
class Gender(enum.Enum):
    FEMALE = 'Weiblich'
    MALE = 'Männlich'

    def __str__(self) -> str:
        return self.value


class NPC:

    def __init__(self, name: str, age: int, gender: Gender, job: str):
        self.name = name
        self.age = age 
        self.gender = gender

        if self.age < 18 and job.lower() != 'schüler':
            raise ValueError('Too young to work')
        if self.age > 65 and job.lower() != 'renter':
            raise ValueError('Too old to work')
        if self.age > 18 and self.age < 65 \
                and job.lower() in ['schüler', 'renter']:
            raise ValueError('NPC need a real job')
        self.job = job 

    def __str__(self) -> str:
        out = f"""
            Der Name des NPC lautet:    {self.name}
            Das Alter des NPC beträgt:  {self.age}
            Das Geschlecht des NPC ist: {self.gender}
            Der Beruf des NPC ist:      {self.job}
            --------------------------------------"""
        return out 


def main() -> None:
    raw_npcs = [ 
        ('Nobert', 54, Gender.MALE, 'Maler'),
        ('Lusia', 29, Gender.FEMALE, 'Bäcker'),
        ('Wolfgang', 71, Gender.MALE, 'Renter'),
        ('Mandy', 12, Gender.FEMALE, 'Schüler'),
        ('Tom', 29, Gender.MALE, 'Putzhilfe'),
        ('Margit', 54, Gender.FEMALE, 'CEO'),
    ]   

    npc_list = []
    for name, age, gender, job in raw_npcs:
        new_npc = NPC(name, age, gender, job)
        npc_list.append(new_npc)

    for npc in sorted(npc_list, key=lambda  x: (x.age, x.name)):
        print(npc)

if __name__ == "__main__":
    main()
                 
Antworten