Seite 1 von 1

Scope in verschachtelten Codeblöcken

Verfasst: Mittwoch 6. August 2008, 10:43
von pcos
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

Verfasst: Mittwoch 6. August 2008, 12:33
von 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.

Verfasst: Mittwoch 6. August 2008, 18:06
von Darii
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>

Verfasst: Mittwoch 6. August 2008, 21:39
von Trundle
@Darii: Probier das mal in einer neuen Session, in der das ``X`` durch vorherige Tests noch nicht existiert.

Verfasst: Mittwoch 6. August 2008, 22:18
von Darii
Ja ok, reingefallen, hatte mich eigentlich schon gewundert dass das geht. ;)