it-swarm.com.de

Durchlaufen einer Liste von Funktionen in einer Funktion in Python dynamisch

Ich würde gerne sehen, ob es möglich ist, eine Liste von Funktionen in einer Funktion auszuführen. Das nächste, was ich finden könnte, ist das Durchlaufen eines gesamten Moduls. Ich möchte nur eine vorgewählte Liste von Funktionen verwenden.

Hier ist mein ursprüngliches Problem:

  1. Überprüfen Sie bei jedem String, ob einer der 5 Tests erfüllt ist.
  2. Wenn mindestens 1 Buchstabe eine Prüfung besteht, geben Sie "Wahr" zurück.
  3. Wenn alle Buchstaben in der Zeichenfolge die Prüfung nicht bestehen, geben Sie False zurück.
  4. Für jeden Buchstaben in der Zeichenfolge werden diese Funktionen überprüft: isalnum (), isalpha (), isdigit (), islower (), isupper ()
  5. Das Ergebnis jedes Tests sollte in verschiedenen Zeilen gedruckt werden. 

Probeneingang

    qA2

Beispielausgabe (muss in separaten Zeilen gedruckt werden, "True", wenn mindestens ein Buchstabe übergeben wird oder "false", wenn alle Buchstaben bei jedem Test nicht bestehen):

    True
    True
    True
    True
    True

Ich habe das für einen Test geschrieben. Natürlich könnte ich nur 5 verschiedene Codes schreiben, aber das scheint hässlich zu sein. Dann begann ich mich zu fragen, ob ich einfach alle Tests durchlaufen könnte, nach denen sie gefragt haben. 

Code für nur einen Test:

    raw = 'asdfaa3fa'
    counter = 0
    for i in xrange(len(raw)):
        if raw[i].isdigit() == True: ## This line is where I'd loop in diff func's
            counter = 1
            print True
            break
    if counter == 0:
        print False

Mein Fehlversuch, eine Schleife mit allen Tests auszuführen:

    raw = 'asdfaa3fa'
    lst = [raw[i].isalnum(),raw[i].isalpha(),raw[i].isdigit(),raw[i].islower(),raw[i].isupper()]
    counter = 0
    for f in range(0,5):
        for i in xrange(len(raw)):
            if lst[f] == True: ## loop through f, which then loops through i
                print lst[f] 
                counter = 1
                print True
        break
        if counter == 0:
    print False

Wie kann ich diesen Code korrigieren, um alle Regeln dort oben zu erfüllen?


Info aus allen Kommentaren verwenden - Dieser Code erfüllt die oben genannten Regeln, wobei jede Methode dynamisch durchlaufen wird.

    raw = 'ABC'
    functions = [str.isalnum, str.isalpha, str.isdigit, str.islower,  str.isupper]

    for func in functions:
        print any(func(letter) for letter in raw)

Getattr-Ansatz (Ich glaube, dies wird als Introspektionsmethode bezeichnet?)

    raw = 'ABC'

    meths = ['isalnum', 'isalpha', 'isdigit', 'islower', 'isupper']
    for m in meths: 
        print any(getattr(c,m)() for c in raw)

Listenverständnisansatz:

    from __future__ import print_function ## Changing to Python 3 to use print in list comp

    raw = 'ABC'
    functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
    solution = [print(func(raw)) for func in functions]
8
jhub1

Die Art und Weise, wie Sie eine Liste von Funktionen durchlaufen, ist etwas deaktiviert. Dies wäre eine gültige Möglichkeit, dies zu tun. Die Funktionen, die Sie in der Liste speichern müssen, sind die generischen Zeichenfolgenfunktionen, die von str.funcname angegeben werden. Sobald Sie diese Liste von Funktionen haben, können Sie sie mit einer for-Schleife durchlaufen und sie wie eine normale Funktion behandeln!

raw = 'asdfaa3fa'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower,  str.isupper]  # list of functions

for fn in functions:     # iterate over list of functions, where the current function in the list is referred to as fn
    for ch in raw:       # for each character in the string raw
        if fn(ch):        
            print(True)
            break

Beispielausgaben:

Input                     Output
===================================
"qA2"         ----->      True True True True True
"asdfaa3fa"   ----->      True True True True

Ich stelle auch fest, dass Sie die Indizierung für die Iteration verwenden, was mir das Gefühl gibt, Sie kommen aus einer Sprache wie C/C++. Das for-in-Schleife-Konstrukt ist in Python wirklich mächtig, also würde ich es (y) nachlesen.

Oben ist ein mehr pythonischer Weg, dies zu tun, aber als Lernwerkzeug habe ich eine funktionierende Version geschrieben, die so aussieht, wie Sie versucht haben, so genau wie möglich zu zeigen, wo Sie gerade falsch liegen. Hier ist es mit Kommentaren:

raw = 'asdfaa3fa'
lst = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]   # notice youre treating the functions just like variables and aren't actually calling them. That is, you're writing str.isalpha instead of str.isalpha()
for f in range(0,5):
    counter = 0
    for i in xrange(len(raw)):
        if lst[f](raw[i]) == True:  # In your attempt, you were checking if lst[f]==True; lst[f] is a function so you are checking if a function == True. Instead, you need to pass an argument to lst[f](), in this case the ith character of raw, and check whether what that function evaluates to is true
            print lst[f] 
            counter = 1
            print True
            break
    if counter == 0:
        print False
8
gowrath

Okay, die erste Frage ist leicht genug. Der einfache Weg, es zu tun, ist einfach zu tun

def foo(raw):
  for c in raw:
    if c.isalpha(): return True
    if c.isdigit(): return True
    # the other cases
  return False

Vernachlässigen Sie niemals die einfachste Sache, die funktionieren könnte.

Wenn Sie es dynamisch - tun möchten, das magische Schlüsselwort, das Sie wahrscheinlich benötigen, möchten Sie etwas wie das folgende anwenden (Krippe aus eine andere Frage ):

meths = [isalnum, isalpha, isdigit, islower, isupper]
for c in raw:    
  for m in meths:
    getattr(c, m)()

Achtung, dies ist ein nicht getesteter Code, der Ihnen die Idee vermittelt. Der Schlüsselbegriff hier ist, dass die Methoden eines Objekts Attribute sind wie alles andere, also führt getattr("a", "isalpha")() Folgendes aus:

  • Verwendet getattr, um das Attributwörterbuch von "a" nach einer Methode namens isalpha zu durchsuchen.
  • Gibt die Methode selbst zurück - <function isalpha>
  • ruft dann diese Methode mit dem () auf, der der Funktionsanwendungsoperator in Python ist.

Siehe dieses Beispiel:

In [11]: getattr('a', 'isalpha')()
Out[11]: True
3
Charlie Martin

Um die ursprüngliche Frage zu beantworten:

raw = 'asdfa3fa'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
isanything = [func(raw) for func in functions]
print repr(isanything)
2
J Earls

Alle anderen Antworten sind korrekt, aber da Sie ein Anfänger sind, möchte ich das Problem in Ihrem Code aufzeigen:

lst = [raw[i].isalnum(),raw[i].isalpha(),raw[i].isdigit(),raw[i].islower(),raw[i].isupper()]

Erstens: Nicht sicher, welcher Wert i aktuell in Ihrem Code abgeschnitten ist, aber er scheint irgendwo in der Zeichenfolge zu zeigen - was dazu führt, dass einzelne Zeichen ausgewertet werden, nicht die gesamte Zeichenfolge raw .

Zweitens: Wenn Sie Ihre Liste erstellen, rufen Sie bereits die Methoden auf, die Sie einfügen möchten. Dies bewirkt, dass nicht die Funktionen selbst eingefügt werden, sondern deren Rückgabewerte (aus diesem Grund werden alle diese Optionen angezeigt: True Werte in Ihrer Druckaussage).

Versuchen Sie, Ihren Code wie folgt zu ändern:

lst = [raw.isalnum, raw.isalpha, raw.isdigit, raw.islower, raw.isupper]
2
andreas-hofmann

Ich vermute, dass Sie die Passwortkomplexität überprüfen, und ich werde auch sagen, dass Software, die eine Eingabe entgegennimmt und "False" sagt, keinen Hinweis darauf gibt, dass warum benutzerfeindlich ist Das Wichtigste ist nicht "wie man verschachtelte Char-Funktionscode-Zauberei (*) durchläuft", sondern "gutes Feedback geben" und etwas anderes vorschlagen:

raw = 'asdfaa3fa'

import re

def validate_password(password):
    """ This function takes a password string, and validates it
        against the complexity requirements from {wherever}
        and returns True if it's complex enough, otherwise False """

    if not re.search('\d', password):
        print("Error: password needs to include at least one number")
        return False

    Elif not re.search('[a-z]', password):
        print("Error: password must include at least one lowercase letter")
        return False

    Elif not re.search('[A-Z]', password):
        print("Error: password must include at least one uppercase letter")
        return False

    print("Password is OK")
    return True

validate_password(raw)

Versuchen Sie es online at repl.it

Und bei der Regex-Suche werden die Zeichen- und Ziffernbereiche in einem Anruf überprüft, was übersichtlicher ist als eine Schleife über Zeichen.

(PS. Ihre Funktionen überlappen sich; eine Zeichenfolge, deren Zeichen mit 'isupper', 'islower' und 'isnumeric' übereinstimmen, enthält bereits 'isadigit' und 'isalnum'). Interessanter wäre es, Zeichen wie ! zu behandeln, die nicht oben, unten sind , Ziffern oder alnum).


(*) Funktionszaubererei wie die anderen Antworten ist normalerweise genau das, was ich antworten würde, aber es gibt so viele Antworten, dass ich auch andersherum antworten könnte: P

2

Da Sie eine Liste einfacher Elemente durchlaufen und versuchen, herauszufinden, ob all der Funktionen any gültige Ergebnisse enthält, können Sie einfach die Liste der Funktionen definieren, die Sie für die Eingabe aufrufen möchten, und diese zurückgeben . Hier ist ein eher pythonisches Beispiel für das, was Sie erreichen wollen:

def checker(checks, value):
    return all(any(check(r) for r in value) for check in checks)

Testen Sie es aus:

>>> def checker(checks, value):
...     return all(any(check(r) for r in value) for check in checks)
... 
>>> checks = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
>>> checker(checks, 'abcdef123ABC')
True
>>> checker(checks, 'abcdef123')
False
>>> 
1
metatoaster

Sie können introspection verwenden, um alle Attribute eines Objekts zu durchlaufen, unabhängig davon, ob es sich um Funktionen oder um einen anderen Typ handelt.

Allerdings möchten Sie das wahrscheinlich nicht hier tun, weil str lots von Funktionsattributen hat und Sie nur an fünf davon interessiert sind. Es ist wahrscheinlich besser, als Sie getan haben, und eine Liste der fünf, die Sie wollen, zu erstellen.

Außerdem müssen Sie nicht jedes Zeichen der Zeichenfolge durchlaufen, wenn Sie dies nicht möchten. Diese Funktionen betrachten bereits die gesamte Zeichenfolge.

1
John Gordon

Sehen Sie sich diese einzeilige Lösung für Ihr Problem an. Dieses Problem stammt von HackerRank. Ich durchlaufe eine Liste von Funktionen mit der eingebauten Funktion getattr.

s='qA2'
[print(bool(list(filter(lambda x : getattr(x, func)(),s)))) for func in ['isalnum','isalpha','isdigit','islower','isupper']]
0
Rajesh Samui