Enumerating through a list of functions in functions in Python dynamically

I would like to see if it is possible to run a list of functions in a function. The closest I could find was a loop through the entire module. I want to use only the pre-selected list of functions.

Here is my original problem:

  • Given the string, check each letter to see if any of the 5 tests have been completed.
  • If at least 1 letter passes the test, return True.
  • If all letters in the string do not pass the test, return False.
  • For each letter in the string, we will check these functions: isalnum (), isalpha (), isdigit (), islower (), isupper ()
  • The result of each test should be printed on different lines.

Input example

qA2 

Sample output (should print for individual lines, True, if at least one letter passes, or false - all letters do not pass each test):

  True True True True True 

I wrote this for one test. Of course, I could just write 5 different sets of code, but that seems ugly. Then I began to wonder if I could just skip all the tests they ask.

Code for only one 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 

My unsuccessful attempt to start a loop with all the 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 

So, how do I fix this code to follow all the rules there?


Using the information from all comments - this code complies with the above rules, also dynamically iterates over each method.

  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 method (I think this is called the introspection method?)

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

List comprehension approach:

  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
python list loops
source share
8 answers

The way you iterate over the list of functions is a bit off. That would be the right way to do this. The functions to be stored in the list are the common string functions given by str.funcname. When you have a list of functions, you can pass them through the for loop and just treat it like a regular function!

 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 

Selective Outputs:

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

I also notice that you seem to be using indexing for iteration, which makes me feel like you can switch from a language like C / C ++. The for in loop construct is really powerful in python, so I would read it (y).

Above is a more pythonic way of doing this, but as a learning tool, I wrote a working version that matches how you tried to do this as much as possible to show you where you were wrong. Here it is with comments:

 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
source share

Good, so the first question is quite simple. Easy way to do it just do

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

Never neglect the simplest thing that could work.

Now, if you want to do it dynamically - this is the magic keyword that you probably need, you want to apply something like this (cut from another question )

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

A warning. This is unverified code designed to give you this idea. The key concept here is that the methods of the object are attributes, like everything else, therefore, for example, getattr("a", "isalpha")() performs the following actions:

  • Uses getattr to find the attribute dictionary "a" for a method named isalpha
  • Returns this method - <function isalpha>
  • then calls this method using () , which is the operator of the function application in Python.

See this example:

 In [11]: getattr('a', 'isalpha')() Out[11]: True 
+3
source share

To answer the original question:

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

All other answers are correct, but since you're new, I want to point out a problem in your code:

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

First: Not sure what value I currently have in your code cut off, but it looks like it is somewhere in the string, which leads to the calculation of single characters, and not the entire raw string.

Secondly: when you create your list, you already call the methods you want to insert, which leads to the fact that the functions themselves are not inserted, but their return values ​​(so you see all these True values ​​in your print statement).

Try changing the code as follows:

 lst = [raw.isalnum, raw.isalpha, raw.isdigit, raw.islower, raw.isupper] 
+2
source share

I'm going to guess that you check the password complexity, and I will also say that the software that enters the input and says β€œFalse” and there is no indication why the user is hostile, so the most important thing is not how to iterate over the nested char function code wizardry (*) ", but" give good feedback "and offer something more:

 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 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('[az]', password): print("Error: password must include at least one lowercase letter") return False elif not re.search('[AZ]', password): print("Error: password must include at least one uppercase letter") return False print("Password is OK") return True validate_password(raw) 

Try it online at repl.it

And a regular expression search checks the ranges of characters and numbers in a single call, which is more accurate than looping over characters.

(PS. Your functions overlap, a line with characters matching "isupper", "islower" and "isnumeric" already has "isadigit" and "isalnum". It would be more interesting to process characters like ! That are not upper, lower, numbers or alnum).


(*) function wizardry, like other answers, is just what I would answer, but there are so many answers already answered that I can answer differently: P

+2
source share

Since you are sorting through a list of simple elements and trying to find if all functions have any valid results, you can simply define the list of functions that you want to call at the input and return them. Here is a pretty pythonic example of what you are trying to achieve:

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

Check this:

 >>> 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
source share

You can use introspection to scroll through all the attributes of an object, whether it be a function or some other type.

However, you probably do not want to do this because str has many function attributes, and you are only interested in five of them. You are probably better off doing what you did, and just make a list of the five you want.

In addition, you do not need to loop over each character of the string if you do not want to; these functions are already looking at the entire line.

+1
source share

Check out this one line solution for your problem. This problem is from HackerRank. I iterate over a list of functions using the built-in getattr function.

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

All Articles