439 Stimmen

Warum ist IoC / DI in Python nicht üblich?

In Java IoC / DI ist eine sehr verbreitete Praxis, die in Webanwendungen, fast allen verfügbaren Frameworks und Java EE ausgiebig genutzt wird. Auf der anderen Seite gibt es auch viele große Python-Webanwendungen, aber abgesehen von Zope (das, wie ich gehört habe, wirklich schrecklich zu programmieren sein soll) scheint IoC in der Python-Welt nicht sehr verbreitet zu sein. (Bitte nennen Sie einige Beispiele, wenn Sie denken, dass ich falsch liege).

Es gibt natürlich mehrere Klone beliebter Java-IoC-Frameworks, die für Python verfügbar sind, springpython zum Beispiel. Aber keiner von ihnen scheint praktisch genutzt zu werden. Zumindest bin ich noch nie auf ein solches Produkt gestoßen. Django o sqlalchemy + <insert your favorite wsgi toolkit here> basierte Webanwendung, die etwas Ähnliches verwendet.

Meiner Meinung nach hat IoC vernünftige Vorteile und würde es einfach machen, z.B. das django-default-user-model zu ersetzen, aber die extensive Nutzung von Schnittstellenklassen und IoC in Python sieht ein wenig seltsam und nicht "pythonisch" aus. Aber vielleicht hat jemand eine bessere Erklärung, warum IoC in Python nicht weit verbreitet ist.

14voto

bcarlso Punkte 2305

Ich habe Python seit einigen Jahren nicht mehr benutzt, aber ich würde sagen, dass es mehr damit zu tun hat, dass es eine dynamisch typisierte Sprache ist als alles andere. Um ein einfaches Beispiel zu nennen: Wenn ich in Java testen wollte, ob etwas ordnungsgemäß in die Standardausgabe geschrieben wurde, könnte ich DI verwenden und einen PrintStream übergeben, um den geschriebenen Text zu erfassen und zu überprüfen. Wenn ich jedoch in Ruby arbeite, kann ich die 'puts'-Methode auf STDOUT dynamisch ersetzen, um die Überprüfung durchzuführen, und DI komplett aus dem Spiel lassen. Wenn der einzige Grund für die Erstellung einer Abstraktion darin besteht, die Klasse zu testen, die sie verwendet (z. B. Dateisystemoperationen oder die Uhr in Java), führt DI/IoC zu unnötiger Komplexität in der Lösung.

13voto

mlvljr Punkte 3829

Eigentlich ist es ziemlich einfach, ausreichend sauberen und kompakten Code mit DI zu schreiben (ich frage mich, ob es ein Problem ist/bleibt pythonisch dann, aber trotzdem :) ), zum Beispiel bevorzuge ich tatsächlich diese Art der Codierung:

def polite(name_str):
    return "dear " + name_str

def rude(name_str):
    return name_str + ", you, moron"

def greet(name_str, call=polite):
    print "Hello, " + call(name_str) + "!"

_

>>greet("Peter")
Hello, dear Peter!
>>greet("Jack", rude)
Hello, Jack, you, moron!

Ja, dies kann als eine einfache Form der Parametrisierung von Funktionen/Klassen betrachtet werden, aber es erfüllt seinen Zweck. Vielleicht sind die standardmäßig enthaltenen Batterien von Python auch hier ausreichend.

P.S. Ich habe auch ein größeres Beispiel für diesen naiven Ansatz unter Dynamische Auswertung einfacher boolescher Logik in Python .

10voto

zsims Punkte 101

IoC/DI ist ein Designkonzept, aber leider wird es oft als ein Konzept verstanden, das für bestimmte Sprachen (oder Typisierungssysteme) gilt. Ich würde es gerne sehen, wenn Dependency Injection Container in Python viel populärer würden. Es gibt Spring, aber das ist ein Super-Framework und scheint eine direkte Portierung der Java-Konzepte zu sein, ohne viel Rücksicht auf "The Python Way".

In Anbetracht der Annotationen in Python 3 beschloss ich, mich an einem vollwertigen, aber einfachen Container für die Injektion von Abhängigkeiten zu versuchen: https://github.com/zsims/dic . Es basiert auf einigen Konzepten aus einem .NET-Abhängigkeitsinjektionscontainer (der IMO fantastisch ist, wenn Sie jemals in diesem Bereich spielen), aber mit Python-Konzepten mutiert.

9voto

ospider Punkte 7323

Schauen Sie sich FastAPI an, es hat Dependency Injection eingebaut. Zum Beispiel:

from fastapi import Depends, FastAPI

async def get_db():
    db = DBSession()
    try:
        yield db
    except Exception:
        db.rollback()
        raise
    finally:
        db.close()

app = FastAPI()

@app.get("/items")
def get_items(db=Depends(get_db)):
    return db.get_items()

8voto

Martin Swanepoel Punkte 322

Ich denke, aufgrund der dynamischen Natur von Python sehen die Leute nicht oft die Notwendigkeit für ein weiteres dynamisches Framework. Wenn eine Klasse von dem new-style 'object' erbt, kann man eine neue Variable dynamisch erstellen ( https://wiki.python.org/moin/NewClassVsClassicClass ).

d.h. In einfachem Python:

#application.py
class Application(object):
    def __init__(self):
        pass

#main.py
Application.postgres_connection = PostgresConnection()

#other.py
postgres_connection = Application.postgres_connection
db_data = postgres_connection.fetchone()

Schauen Sie sich jedoch an https://github.com/noodleflake/pyioc Dies könnte das sein, wonach Sie suchen.

d.h. Bei Pyiok

from libs.service_locator import ServiceLocator

#main.py
ServiceLocator.register(PostgresConnection)

#other.py
postgres_connection = ServiceLocator.resolve(PostgresConnection)
db_data = postgres_connection.fetchone()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X