Seite 1 von 1

Systemabhängig verschiedene Klassen instanzieren

Verfasst: Mo Jul 04, 2011 9:53 pm
von Dirty Oerti
Tag zusammen :)

Das ist keine Frage, mehr eine Info. Eigentlich gehört sowas ja ins Wiki, da haben wir aber im Bezug auf Python noch viel zu wenig, als dass ich das sinnvoll einordnen kann. Außerdem hätte ich gerne Resonanz zu der grundsätzlich angewandten Technik.

Problemstellung ist:
Ich habe eine gewisse Funktionalität, die ich in Form einer Klasse anbieten will.
Die Schnittstelle ist fest vorgegeben.
Die Funktionalität ist jedoch auf verschiedenen Betriebssystemen unterschiedlich zu implementieren.
Davon soll der Nutzer der Funktionalität aber rein gar nichts mitbekommen.

Mein Ansatz dazu war nun der folgende:


Ein Modul "Func", das die Schnittstelle der Funktionalität bereitstellt.
Ein Modul "XXXXFunc", wobei XXXX für die jeweilige Plattform steht, welches die Funktionalität implementiert.

Code: Alles auswählen

class Func(object):
  def __new__(cls, *args, **kwargs):
    return object.__new__(platform_cls)
Nun musst natürlich zur Laufzeit die zu verwendende Klasse "platform_cls" gefunden werden.
Basis der Überlegungen bildete folgende Funktion:

Code: Alles auswählen

def get_class( kls ):
  parts = kls.split('.')
  module = ".".join(parts[:-1])
  if module:
    m = __import__( module )
    for comp in parts[1:]:
      m = getattr(m, comp)
  return m
Ergebnis der Bastelei:

Ein Package "functionality", das die Schnittstelle im Modul "Func" enthält und, je nach System, die Implementierung "XXXXFunc"

functionality:
--- __init__.py
--- Func.py
--- LinuxFunc.py

__init__.py ist leer, könnte z.B. so eingestellt werden, dass nur Func imported wird, sollte jemand das ganze Package importieren.

Func.py

Code: Alles auswählen

import platform

class Func(object):
  def __new__(cls, *args, **kwargs):
    name = platform.system() + 'Func'
    instance = None
    try:
      m = __import__('functionality.' + name)
      m = getattr(m, name)
      m = getattr(m, name) 
      instance = object.__new__(m) #TODO: Evtl args und kwargs mitgeben?!?
    except (ImportError, AttributeError, TypeError):
      raise NotImplementedError("Not implemented for your system!")
    return instance

  def something(self, foo):
    raise NotImplementedError("Not implemented for your system!")
LinuxFunc.py

Code: Alles auswählen

import functionality.Func

class LinuxFunc(functionality.Func.Func):
  def something(self, foo):
    print "hi", foo

Angewandt wird das nun so:

Code: Alles auswählen

from functionality.Func import Func

f = Func()
f.something('Du da')
print f
Was haltet ihr von diesem Vorgehen?

Re: Systemabhängig verschiedene Klassen instanzieren

Verfasst: So Jul 10, 2011 2:09 pm
von Panke
Viel zu kompliziert. Kannst du nicht einfach die entsprechende Klasse abhängig vom System
in Func an einen Namen binden?

Code: Alles auswählen

#in func.py

if __system__ == "LINUX":
    import MyLinuxClass from func_linux
    MyClass = MyLinuxClass
elif ...

Re: Systemabhängig verschiedene Klassen instanzieren

Verfasst: So Jul 10, 2011 2:57 pm
von Dirty Oerti
Kann ich dann - um mal bei deinem Beispiel zu bleiben - func.py importieren und einfach eine Instanz von (in diesem Fall) MyLinuxClass über MyClass() bekommen?

Re: Systemabhängig verschiedene Klassen instanzieren

Verfasst: Mo Jul 11, 2011 6:23 pm
von Panke
Ja. Habs gerade nochmal extra ausprobiert.

Re: Systemabhängig verschiedene Klassen instanzieren

Verfasst: Mo Jul 11, 2011 10:24 pm
von Dirty Oerti
Cool! :)
Das werde ich evtl übernehmen ... ich brauche ja außerdem sozusagen ein Singleton, wobei ich das auch anders lösen kann ... mal gucken ;)

Re: Systemabhängig verschiedene Klassen instanzieren

Verfasst: Mo Jul 11, 2011 11:36 pm
von Panke
Ist Singleton nicht mittlerweile ein Anti-Pattern? In Python sieht man das imo eher selten.
Wenn dann würd ich ein Modul nehmen. Das sind im Grunde Singletons.