Scope in verschachtelten Codeblöcken

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
pcos
User
Beiträge: 16
Registriert: Dienstag 3. April 2007, 14:21

Hallo zusammen,

das folgende Beispiel 1 läuft ohne Probleme...

Code: Alles auswählen

class A1(object):
    pass

class B1(object):
    a = A1()
... wohingegen beim selben Code in einem class-Block (Bsp. 2)

Code: Alles auswählen

class X(object):
    class A2(object):
        pass
    class B2(object):
        a = A2()
ein NameError in der letzten Zeile auftritt.

Bsp. 1 funktioniert, weil auf Modulebene unmittelbar nach Ausführen der ersten Klassendef. der Name A1 an die Klasse gebunden wird und damit global ist, also inbesondere in der Def. von B1 darauf zugegriffen werden kann. Bsp. 2 funktioniert nicht, weil beim Ausführen der Klassendef. von B2 die Klasse A2 zwar existiert, der Name A2 aber nur in einem dict steht, das später mal zu X.__dict__ wird.

(Wenn diese Erklärungen nicht stimmen, lasse ich mich gerne eines Besseren belehren...)

Meine Frage dazu: Gibt es überhaupt eine Möglichkeit, in B2 auf A2 zuzugreifen? Ich meine nicht mittels X.A2 in irgendwelchen Methoden von B2, sondern im Code, der zur Konstruktion von B2 ausgeführt wird, wenn X noch gar nicht existiert. "Irgendwie" steht der Name A2 schon zur Verfügung; der folgende Code...

Code: Alles auswählen

class X(object):
    class A2(object):
        pass
    class B2(A2):
        pass
... würde ja funktionieren. Allerdings wird auf A2 hier im selben Block zugegriffen, in dem A2 auch def. wird.

In Bsp. 2 sehe ich nur die Möglichkeit, die Klasse A2 an einen globalen Namen zu binden oder sonst explizit einen Zugriff zu schaffen.

Das Ganze ist sicherlich ein ausgefalles Beispiel, und normalerweise bin ich kein Freund von "lokalen" Klassen. In meiner Anwendung ist X von unittest.TestCase abgeleitet, und A2 und B2 sind nur für die Tests in X relevant. Deshalb fände ich es hier konsequent, A2 und B2 im Namespace von X abzulegen.

Viele Grüße
pcos
BlackJack

Was man machen kann, ist folgendes:

Code: Alles auswählen

class X(object):
    class A2(object):
        pass 
    class B2(object):
        pass

X.B2.a = X.A2()
Aber "innere" Klassen sind in Python eigentlich unüblich.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Was spricht denn jetzt gegen X.A2?

Code: Alles auswählen

In [17]: class X():
    class A2(object): pass
    class B2(object): a = X.A2()
   ....:     
   ....:     

In [20]: X.B2.a

Out[20]: <__main__.A2 object at 0x4a35f0>
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

@Darii: Probier das mal in einer neuen Session, in der das ``X`` durch vorherige Tests noch nicht existiert.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Ja ok, reingefallen, hatte mich eigentlich schon gewundert dass das geht. ;)
Antworten