J'aimerais voir s'il est possible de parcourir une liste de fonctions dans une fonction. La chose la plus proche que je puisse trouver est de parcourir tout un module. Je veux seulement utiliser une liste de fonctions présélectionnée.
Voici mon problème d'origine:
Exemple de saisie
qA2
Exemple de sortie (doit être imprimé sur des lignes séparées, True si au moins une lettre est réussie ou false si toutes les lettres échouent à chaque test):
True
True
True
True
True
J'ai écrit ceci pour un test. Bien sûr, je pourrais simplement écrire 5 ensembles de code différents, mais cela semble moche. Ensuite, j'ai commencé à me demander si je pouvais simplement passer en revue tous les tests demandés.
Code pour un seul 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
Ma tentative d’échec pour exécuter une boucle avec tous les tests:
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
Alors, comment puis-je corriger ce code pour respecter toutes les règles là-haut?
Utilisation des informations de tous les commentaires - ce code respecte les règles énoncées ci-dessus, en passant en revue chaque méthode de manière dynamique.
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)
Approche getattr (je pense qu’on appelle cela une méthode d’introspection?)
raw = 'ABC'
meths = ['isalnum', 'isalpha', 'isdigit', 'islower', 'isupper']
for m in meths:
print any(getattr(c,m)() for c in raw)
Approche de compréhension de liste:
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]
La façon dont vous parcourez une liste de fonctions est légèrement différente. Ce serait un moyen valable de le faire. Les fonctions que vous devez stocker dans la liste sont les fonctions de chaîne génériques données par str.funcname. Une fois que vous avez cette liste de fonctions, vous pouvez les parcourir en utilisant une boucle for, et la traiter comme une fonction normale!
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
Exemples de sortie:
Input Output
===================================
"qA2" -----> True True True True True
"asdfaa3fa" -----> True True True True
De plus, je remarque que vous semblez utiliser l'indexation pour l'itération, ce qui me donne l'impression que vous venez peut-être d'un langage comme le C/C++. La construction de la boucle in est vraiment puissante en python, je la lirais donc (y).
Ci-dessus est une manière plus pythonique de le faire, mais juste comme outil d’apprentissage, j’ai écrit une version de travail qui correspond à la façon dont vous avez essayé de le faire autant que possible pour vous montrer précisément où vous vous êtes trompé. La voici avec des commentaires:
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
D'accord, la première question est assez simple. La façon simple de le faire est juste faire
def foo(raw):
for c in raw:
if c.isalpha(): return True
if c.isdigit(): return True
# the other cases
return False
Ne négligez jamais la chose la plus simple qui puisse fonctionner.
Maintenant, si vous voulez le faire dynamiquement - qui est le mot clé magique dont vous avez probablement besoin, vous voulez appliquer quelque chose comme ceci (cribbed à partir de une autre question ):
meths = [isalnum, isalpha, isdigit, islower, isupper]
for c in raw:
for m in meths:
getattr(c, m)()
Attention, ce code non testé a pour but de vous donner une idée. La notion clé ici est que les méthodes d'un objet sont des attributs comme toute autre chose, ainsi, par exemple, getattr("a", "isalpha")()
fait ce qui suit:
getattr
pour rechercher dans le dictionnaire d'attributs de "a"
une méthode nommée isalpha
<function isalpha>
()
qui est l'opérateur d'application de la fonction en Python.Voir cet exemple:
In [11]: getattr('a', 'isalpha')()
Out[11]: True
Pour répondre à la question initiale:
raw = 'asdfa3fa'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
isanything = [func(raw) for func in functions]
print repr(isanything)
Toutes les autres réponses sont correctes, mais comme vous êtes débutant, je tiens à signaler le problème dans votre code:
lst = [raw[i].isalnum(),raw[i].isalpha(),raw[i].isdigit(),raw[i].islower(),raw[i].isupper()]
Premièrement: vous ne savez pas quelle valeur i a actuellement été coupée dans votre code, mais elle semble pointer quelque part dans la chaîne, ce qui entraîne l'évaluation de caractères uniques et non de la chaîne entière raw .
Deuxièmement: lorsque vous construisez votre liste, vous appelez déjà les méthodes que vous souhaitez insérer, ce qui a pour effet que ce ne sont pas les fonctions elles-mêmes qui sont insérées, mais leurs valeurs de retour (c'est pourquoi vous voyez toutes ces True valeurs dans votre relevé d'impression).
Essayez de changer votre code comme suit:
lst = [raw.isalnum, raw.isalpha, raw.isdigit, raw.islower, raw.isupper]
Je vais deviner que vous validez la complexité du mot de passe, et je vais aussi dire que le logiciel prend une entrée et dit "Faux" et qu'il n'y a aucune indication pourquoi est hostile à l'utilisateur, donc La chose la plus importante n’est pas de savoir "faire une boucle sur la magie du code de la fonction char imbriquée (*)" mais de "donner un bon retour", et de suggérer quelque chose de plus semblable à:
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)
Essayez en ligne sur repl.it
Et la recherche regex vérifie les plages de caractères et de chiffres dans un appel, ce qui est plus pratique qu'une boucle sur des caractères.
(PS. Vos fonctions se chevauchent; une chaîne dont les caractères correspondent à "isupper", "islower" et "isnumeric" est déjà couverte par "isadigit" et "isalnum". Plus intéressant serait de traiter des caractères comme !
qui ne sont pas supérieur, inférieur , chiffres ou alnum).
(*) la magie des fonctions comme les autres réponses correspond normalement à ce que je répondrais, mais il y a tellement de réponses que j'ai déjà répondu que je pourrais aussi bien répondre à l'inverse: P
Puisque vous parcourez une liste d’items simples et que vous essayez de trouver si all
des fonctions a any
résultats valides, vous pouvez simplement définir la liste des fonctions que vous souhaitez appeler et le renvoyer. . Voici un exemple plutôt pythonique de ce que vous essayez d’atteindre:
def checker(checks, value):
return all(any(check(r) for r in value) for check in checks)
Testez-le:
>>> 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
>>>
Vous pouvez utiliser introspection pour parcourir en boucle tous les attributs d’un objet, qu’il s’agisse de fonctions ou d’un autre type.
Cependant, vous ne voulez probablement pas faire cela ici, parce que str
a lots d'attributs de fonction et que cinq d'entre eux ne vous intéressent. Il vaut probablement mieux faire ce que vous avez fait et dressez une liste des cinq que vous voulez.
En outre, vous n'avez pas besoin de passer en boucle sur chaque caractère de la chaîne si vous ne le souhaitez pas; ces fonctions regardent déjà toute la chaîne.
Découvrez cette solution en une ligne pour votre problème. Ce problème vient de HackerRank. Je parcours une liste de fonctions à l’aide de la fonction getattr intégrée.
s='qA2'
[print(bool(list(filter(lambda x : getattr(x, func)(),s)))) for func in ['isalnum','isalpha','isdigit','islower','isupper']]