Variablen von Hauptklasse nach Subklasse ohne Klammernüberga

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
Papp Nase
User
Beiträge: 139
Registriert: Dienstag 11. März 2014, 15:12

Guten Abend!

Ich möchte in einer Hauptklasse eine Subklasse erstellen und auf die Variablen der Hauptklasse drauf zugreifen zu können. Dies kann ich tun, in dem ich alle Werte übergebe:

Code: Alles auswählen

class Hauptklasse:
    def __init__(self):
        self.variable1 = 1
        self.variable2 = 2
        self.SubKlasse(self.variable1, self.variable2)
        
    class SubKlasse:
        def __init__(self, var1, var2):
            self.variable1 = var1
            self.variable2 = var2
            
            print (self.variable1) 
Ich habe es mit einem "self" probiert:

class SubKlasse(self)

damit dann alle self-Dinger der Hauptklasse in der Subklasse auch mit übergeben werden, aber das ging leider nicht. Geht das überhaupt oder muss ich wie in dem ersten Beispiel die Werte alle so dierekt übergeben?
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Mal absehen davon dass ich das Design für kompletten Murks halte und das geschriebene bestenfalls zu einem Drittel verstehe, bist du sicher das du das Thema OOP komplett durchdrungen hast? Das Beispiel ist mehr als nur sinnfrei. Wieso erbt die Subklasse nicht von der Hauptklasse?
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Papp Nase
User
Beiträge: 139
Registriert: Dienstag 11. März 2014, 15:12

darktrym hat geschrieben:Mal absehen davon dass ich das Design für kompletten Murks
Wie würdest Du es denn anders designen?
BlackJack

@Papp Nase: Kann es sein dass Du versuchst so etwas wie innere Klassen bei Java in Python zu verwenden? Das geht so nicht. Es macht selten bis nie Sinn in Python Klassen *in* Klassen zu definieren. Was versuchst Du dadurch zu erreichen? Das müsstest Du verraten wenn man mehr dazu sagen können soll als „so nicht”. :-)
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Man könnte sowas machen:

Code: Alles auswählen

class Outer:

    def __init__(self, value):
        self.value = value

    @property
    class Inner:
        def __init__(self, outer):
            self.outer = outer

o = Outer(7)
sub = o.Inner
assert sub.outer is o
print(sub.outer.value, type(sub), type(sub.outer))
Ergebnis:

Code: Alles auswählen

7 <class '__main__.Inner'> <class '__main__.Outer'>
Aber es ist schon sehr magisch, weswegen ich es nicht uneingeschränkt empfehlen kann. Man sollte nicht nur erklären können, was da passiert, sondern auch warum. Generell sollte man nur Code schreiben, den man auch versteht. Falls man den eigenen Code nicht völlig versteht, wie sollte man ihn richten können, wenn er mal nicht funktioniert? Brian Kernighan hat das schön formuliert: Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Papp Nase hat geschrieben:Ich möchte in einer Hauptklasse eine Subklasse erstellen [...]
Da fragen wir doch einfach mal: Warum?

Bitte beschreibe deinen konkreten Anwendungsfall, das Design sieht nämlich mächtig verhunzt aus.
Papp Nase
User
Beiträge: 139
Registriert: Dienstag 11. März 2014, 15:12

Ich habe eine Klasse, die eine run-Funktion hat:

Code: Alles auswählen

class CreateRandoms(threading.Thread):
    
    def __init__(self, data):
        threading.Thread.__init__(self)
        self._abort = False
        self._data = data
        
    def run(self):
        self._abort = True
        while self._abort == True:
            rand = random.randrange(2)
            if rand == 0:
                self._data.set_false()
            elif rand == 1:
                self._data.set_true()
            time.sleep(100/1000)
                
        
    def stopp(self):
        self._abort = False
Ich habe versucht, den Thread zu beenden und dann wieder zu starten. Aber der zweite Start ging völlig daneben:

Code: Alles auswählen

if __name__ == '__main__':
    myrandoms=CreateRandoms()
    myrandoms.start()
    myrandoms.stopp()
    myrandoms.join()
    
    myrandoms.start()
    
Ich kann also ein einmal beendetes Objekt nicht wieder neu starten. Also möchte ich in der Klasse CreateRandoms eine Subklasse haben, die ich mit threading als Klasse innerhalb der Klasse aufrufen kann.

Meine neue Idee (funktioniert noch nicht ganz):

Code: Alles auswählen

class CreateRandoms(threading.Thread):
    
    def __init__(self, data):
        threading.Thread.__init__(self)
        self._abort = False
        self._data = data
        self._subklasse = self.SubKlasse()
        
    """def run(self):
        self._abort = True
        while self._abort == True:
            rand = random.randrange(2)
            if rand == 0:
                self._data.set_false()
            elif rand == 1:
                self._data.set_true()
            time.sleep(100/1000) """
                
        
    def stopp(self):
        self._abort = False
    
    def startcreatingrandoms(self):
        if self._subklasse.is_alive() == False:
            self._subklasse=self.SubKlasse()   # Subklasse neu zuweisen, weil alte Klasse nicht nochmal gestartet werden kann
            self._subklasse.start()
                
            
        
    class SubKlasse(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            
        def run(self):
    
            self._abort = True
            while self._abort == True:
                rand = random.randrange(2)
                if rand == 0:
                    self._data.set_false()
                elif rand == 1:
                    self._data.set_true()
                time.sleep(100/1000)
Jetzt würde ich gerne in der Subklasse ohne Argumentübergabe auch auf die self.-Dinger von der Hauptklasse CreateRandoms drauf zugreifen können, damit ich dann die SubKlasse ganz einfach auch beenden kann und alle Parametrierungen aus der Hauptklasse gleich in der SubKlasse ohne Argumentenübergabe habe.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Papp Nase: normalerweise werden Threads erzeugt, um eine bestimmte Aufgabe zu erledigen, so dass das Objekt nicht mehr gebraucht wird, wenn der Thread einmal durchgelaufen ist.
Was willst Du denn mit Deinem Starten und Stoppen erreichen?
BlackJack

@Papp Nase: Das sieht ziemlich umständlich und ”klassenlastig” aus. Das was Du möchtest geht nicht und darum macht es auch keinen Sinn die Klasse in der anderen zu definieren.

Edit: `_abort` ist der falsche Name beziehungsweise hast Du die Belegung für diesen Namen genau falsch herum.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Papp Nase: Mir ist absolut ncht klar, wozu du da Threads brauchst:

Code: Alles auswählen

import itertools
import random

true_or_false = iter(lambda: random.choice((True, False)), None)

class StoppableIterator:
    def __init__(self, iterable):
        self.running = iterable
        self.stopped = False
        self.current = None
    def stop(self):
        if self.stopped:
            return
        self.stopped = True
        self.current = next(self.running)
    def resume(self):
        if not self.stopped:
            return
        self.stopped = False
        self.current = None
    def __iter__(self):
        while True:
            if self.stopped:
                yield self.current
            else:
                yield next(self.running)

stopiter = StoppableIterator(true_or_false)
for i, each in zip(range(7), stopiter):
    print i, each

stopiter.stop()
for i, each in zip(range(7), stopiter):
    print i, each

stopiter.resume()
for i, each in zip(range(7), stopiter):
    print i, each
Ergebnis:

Code: Alles auswählen

0 True
1 True
2 False
3 True
4 True
5 False
6 True
0 True
1 True
2 True
3 True
4 True
5 True
6 True
0 False
1 False
2 False
3 False
4 False
5 True
6 True
Wenn es dir darum geht, mit threading herumzuspielen um herauszukriegen, wie das funktioniert, dann empfehle ich das Buch "Concurrent Programming in Java, 2nd Ed." von Doug Lea. Es ist zwar für Java, aber Pythons threading.Thread ist den Java-Threads nachempfunden, weswegen man den Java-Code aus dem Buch leicht nach Python übertragen kann, selbst wenn man nicht soviel von Java versteht.

Multithreading ist ein schwieriges Thema, das man durch reines Ausprobieren nicht zu durchdringen lernt. Da braucht man eine Anleitung, sonst baut man entweder Sachen, die überhaupt nicht funktionieren, oder man erfindet andauernd Dinge, die andere schon besser implementiert haben.
In specifications, Murphy's Law supersedes Ohm's.
Antworten