2017-05-11 2 views
0

Also habe ich diesen Code:Python: Ungelöste Bezug auf Klasse von statischen Variablen

class MyClass: 

    ACTIONS = { 
     "ACTION_A": MyClass.__a, 
     "ACTION_B": MyClass.__b 
    } 

    @staticmethod 
    def do(constant): 
     ACTIONS[constant]() 

    @staticmethod 
    def __a(): 
     print("A") 

    @staticmethod 
    def __b(): 
     print("B") 

Ich versuche, die privaten __A und __B Funktionen auf ein statisches Wörterbuch zu kartieren, damit ich bin in der Lage um Funktionen mit der Methode do auszuführen.

Beim Versuch, diesen Code ich den Fehler ausführen: „Ungelöste Referenz‚MyClass‘“ auf jede Zeile des AKTIONEN Wörterbuch.

Haben Sie eine Idee, wie das funktioniert?

+0

In Python 'static' bedeutet etwas anderes aus dem gleichen Schlüsselwort in Java. Verwenden Sie es nicht, um Daten pro Klasse zu verwalten. Verwenden Sie 'classmethod's dafür. –

+0

Und, nein, "MyClass" ist noch nicht definiert, wenn das Mapping "ACTIONS" erstellt wird. Dieser Name wird gesetzt * nachdem die 'class' Anweisung abgeschlossen ist *. –

+0

Nicht zuletzt verwenden Sie keine '__name'-Stilattribute, es sei denn, Sie erstellen eine Basisklasse, in der sich Unterklassen nicht darum kümmern müssen, welche Namen kollidieren könnten (wie in einem Framework). Es gibt hier kein Java-ähnliches Datenschutzmodell, diese Attribute sind * für externe Anrufer * nicht zugänglich. Sie geben den Attributen nur einen anderen Namensraum. –

Antwort

5

Sie sollten in erster Linie keine Klasse verwenden. Sie erstellen lediglich einen Namespace, verwenden ein Modul dafür. Erstellen Sie ein neues Modul in einem Paket und setzen alle Funktionen, dass:

def _a(): 
    print("A") 

def _b(): 
    print("B") 


ACTIONS = { 
    'ACTION_A': _a, 
    'ACTION_B': _b, 
} 

def do(constant): 
    ACTIONS[constant]() 

Bitte beachte, dass ich verwendet einzelne Namen unterstreichen. Python verwendet doppelte Unterstrichnamen in Klassen, um einen zusätzlichen Namespace pro Klasse zu erstellen. MyClass.__a wird MyClass._MyClass__a, um Konflikte mit Unterklassen zu vermeiden (so dass sie Namen problemlos wiederverwenden können, ohne Angst davor zu haben, die Implementierung einer Superklasse zu unterbrechen), gibt es in Python kein Datenschutzmodell.

Sie könnten einen Dekorateur verwenden, um die _a und _b Funktionen zu registrieren:

def do(constant): 
    ACTIONS[constant]() 

ACTIONS = {} 

def action(name): 
    def decorator(f): 
     ACTIONS[name] = f 
     return f 

@action('ACTION_A') 
def _a(): 
    print("A") 

@action('ACTION_B') 
def _b() 
    print("B") 

Der spezifische Fehler, den Sie ist sehen aufgrund der MyClass Name nicht gesetzt werden, bis die gesamte class Anweisung abgeschlossen hat. Sie würden dieses Wörterbuch setzen haben danach:

class MyClass: 
    @classmethod 
    def do(cls, constant): 
     cls.ACTIONS[constant]() 

    @staticmethod 
    def _a(): 
     print("A") 

    @staticmethod 
    def _b(): 
     print("B") 

MyClass.ACTIONS = { 
    'ACTION_A': MyClass._a, 
    'ACTION_B': MyClass._b, 
} 

Beachten Sie, dass do eine Klassenmethode ist, können Sie nicht nur ACTIONS als globaler zuzugreifen, müssen Sie entweder MyClass.ACTIONS oder verwenden, wie ich oben verwendet , dann referenziere eine Klassenmethode das Objekt auf cls.

Sie arbeiten rund um konnten mit ACTIONS nach der class Anweisung zu setzen, indem Namen stattdessen verwenden und def do eine Klassenmethode machen:

class MyClass: 
    ACTIONS = { 
     'ACTION_A': '_a', 
     'ACTION_B': '_b', 
    } 

    @classmethod 
    def do(cls, constant): 
     getattr(cls, cls.ACTIONS[constant])() 

    @staticmethod 
    def _a(): 
     print("A") 

    @staticmethod 
    def _b(): 
     print("B") 
+0

Das ist wirklich interessant, ich habe ein paar wertvolle Python-Konzepte gelernt. Danke für deine Einsicht. – Strinnityk

Verwandte Themen