Frage

ich nicht wirklich so viel Aufmerksamkeit auf die Entwicklung Python 3 ist zu zahlen, wie ich es mir gewünscht hätte, und nur gerade einige interessante neue Syntax Veränderungen bemerkt. Insbesondere von Beantwortung dieser Frage SO Funktionsparameter Anmerkung:

def digits(x:'nonnegative number') -> "yields number's digits":
    # ...

Nicht etwas darüber zu wissen, dachte ich es vielleicht für die Implementierung statische Typisierung in Python verwendet werden könnte!

Nach einiger Suche, schien es viel Diskussion über (völlig optional) statische Typisierung in Python zu sein, wie sie unter PEP 3107 und "Hinzufügen Optional statische Typisierung zu Python" (und Teil 2 )

.. aber ich bin mir nicht klar, wie weit diese fortgeschritten ist. Gibt es Implementierungen von statischer Typisierung, mit der Parameter-Annotation? Hat einer der parametrisiert artigen Ideen macht es in Python 3?

War es hilfreich?

Lösung

Vielen Dank für das Lesen meiner Code!

Ja, es ist nicht schwer, eine allgemeine Anmerkung Enforcer in Python zu erstellen. Hier ist mein nehmen:

'''Very simple enforcer of type annotations.

This toy super-decorator can decorate all functions in a given module that have 
annotations so that the type of input and output is enforced; an AssertionError is
raised on mismatch.

This module also has a test function func() which should fail and logging facility 
log which defaults to print. 

Since this is a test module, I cut corners by only checking *keyword* arguments.

'''

import sys

log = print


def func(x:'int' = 0) -> 'str':
    '''An example function that fails type checking.'''
    return x


# For simplicity, I only do keyword args.
def check_type(*args):
    param, value, assert_type = args
    log('Checking {0} = {1} of {2}.'.format(*args))
    if not isinstance(value, assert_type):
        raise AssertionError(
            'Check failed - parameter {0} = {1} not {2}.'
            .format(*args))
    return value

def decorate_func(func):    
    def newf(*args, **kwargs):
        for k, v in kwargs.items():
            check_type(k, v, ann[k])
        return check_type('<return_value>', func(*args, **kwargs), ann['return'])

    ann = {k: eval(v) for k, v in func.__annotations__.items()}
    newf.__doc__ = func.__doc__
    newf.__type_checked = True
    return newf

def decorate_module(module = '__main__'):
    '''Enforces type from annotation for all functions in module.'''
    d = sys.modules[module].__dict__
    for k, f in d.items():
        if getattr(f, '__annotations__', {}) and not getattr(f, '__type_checked', False):
            log('Decorated {0!r}.'.format(f.__name__))
            d[k] = decorate_func(f)


if __name__ == '__main__':
    decorate_module()

    # This will raise AssertionError.
    func(x = 5)

Diese Einfachheit Da es auf dem ersten Blick seltsam, dass dieses Ding nicht Mainstream ist. Aber ich glaube, es gibt gute Gründe, warum es nicht so nützlich, wie es scheinen mag . Im Allgemeinen hilft Typprüfung, denn wenn Sie integer und Wörterbuch hinzuzufügen, stehen die Chancen, machte man einige offensichtliche Fehler (und wenn Sie etwas Vernünftiges gemeint, es ist immer noch , besser zu sein explizit als implizite ).

Aber im wirklichen Leben, das Sie oft mischen Mengen derselben Computertyp , wie Compiler gesehen, aber deutlich anders menschlichen Typ , zum Beispiel das folgende Snippet einen offensichtlichen Fehler enthält:

height = 1.75 # Bob's height in meters.
length = len(sys.modules) # Number of modules imported by program.
area = height * length # What's that supposed to mean???

Jeder Mensch sollte sofort einen Fehler in der oberen Zeile sehen, sofern sie die ‚menschliche Art‘ von Variablen height kennen und length obwohl es um Computer sieht aus, als vollkommen legal Multiplikation von int und float.

Es gibt mehr, die über mögliche Lösungen für dieses Problem kann gesagt werden, aber ‚Computertypen‘ ist offenbar eine halbe Lösung, so, zumindest meiner Meinung nach der Durchsetzung, ist es schlimmer als gar keine Lösung überhaupt . Es ist der gleiche Grund, warum Systeme Ungarisch eine schreckliche Idee ist, während Apps Ungarisch ein großes ist. Es gibt mehr im sehr informativ Beitrag von Joel Spolsky .

Nun, wenn jemand war eine Art von Pythonic Drittanbieter-Bibliothek zu implementieren, die zu seinem realen Daten automatisch zuweisen würden menschlicher Typ und dann kümmerte diese Art wie width * height -> area zu transformieren und dass der Check erzwingen mit Funktion Anmerkungen, denke ich, dass eine Art Überprüfung Menschen nutzen könnten wirklich sein würde!

Andere Tipps

Wie in diesem PEP erwähnt, statische Typprüfung ist eine der möglichen Anwendungen, die Anmerkungen funktionieren kann verwendet werden, aber sie sind so dass es bis zu Bibliotheken von Drittanbietern zu entscheiden, wie es zu tun. Das heißt, es ist keine offizielle Implementierung in Kern Python sein wird.

Soweit Dritt Implementierungen betroffen sind, gibt es einige Schnipsel (wie http: // code.activestate.com/recipes/572161/ ), scheinen die den Job ziemlich gut zu tun.

EDIT:

Als Hinweis, möchte ich erwähnen, dass das Verhalten Prüfung vorzuziehen ist Typ Überprüfung, deshalb denke ich, statische Typprüfung ist nicht so groß, eine Idee. Meine Antwort oben bei der Beantwortung der Frage richtet, nicht, weil ich tun würde mich so Typprüfung.

Dies ist keine Antwort direkt zu fragen, aber ich fand eine Python berappen, die statische Typisierung ergänzt: mypy- lang.org , natürlich kann man sich nicht darauf verlassen, da es immer noch kleines Bestreben ist, aber interessant.

„Static Typisierung“ in Python kann nur umgesetzt werden, so dass die Typprüfung in der Laufzeit erfolgt, was bedeutet, es verlangsamt die Anwendung. Deshalb wollen Sie nicht, dass als Allgemeinheit. Stattdessen möchten Sie einige Ihrer Methoden ist es Eingaben zu überprüfen. Dies kann leicht mit einfachen behauptet, oder mit Dekorateure getan werden, wenn man (fälschlicherweise) denken Sie es brauchen viel.

Es gibt auch eine Alternative zu statischer Typprüfung, und das ist eine Aspekt orientierte Komponentenarchitektur wie The Zope Component Architecture zu verwenden. Statt die Art der Überprüfung, passen Sie es. Anstatt also:

assert isinstance(theobject, myclass)

Sie dies tun:

theobject = IMyClass(theobject)

Wenn theObject bereits implementiert IMyClass nichts passiert. Wenn es nicht der Fall ist, ein Adapter, der theObject wickelt, was zu IMyClass ist wird nachgeschlagen und statt theObject verwendet. Wenn kein Adapter gefunden wird, erhalten Sie einen Fehler.

Diese kombinierte die dynamicism von Python mit dem Wunsch, eine bestimmte Art in einer bestimmten Art und Weise zu haben.

Sicher scheint statische Typisierung ein bisschen „unpythonic“ und ich verwende es nicht die ganze Zeit. Aber es gibt Fälle (zum Beispiel Klassen verschachtelt, wie in domänenspezifische Sprache Parsing), wo es wirklich Ihre Entwicklung beschleunigen kann.

Dann habe ich lieber mit beartype erklärt in diesem post *. Es kommt mit einem git Repo, Tests und eine Erklärung, was es kann und was es nicht kann ... und Ich mag den Namen;)

* Bitte zahlen Sie nicht die Aufmerksamkeit auf Cecils schimpfen darüber, warum Python kommt nicht mit Batterien in diesem Fall enthalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top