1

So, I was working on a Python function that receives a numeric list as a parameter and processes it, just like this example:

def has_string(myList: list) -> str:

    # Side cases
    if myList == []:
        return "List shouldn't be empty"

    if myList contains any str object:  # Here's the problem
        return "List contains at least one 'str' object"

    return "List contains only numeric values"

I've tried some approaches, like:

  1.  if str in my_list:     # return message
    
  2.  if "" in my_list:      # return message
    
  3.  if my_list.count(""):  # return message
    

I did not want to create a for loop and check each item one by one. I wanted to avoid passing through all the items just to tell whether or not my list contains a string.

As I mentioned before, I've tried some different ways to check it within the if block, but none of them worked. The program still continued to process the list even though there was a condition to stop it.

Any help is greatly appreciated, thanks in advance!

5
  • 1
    It is not possible without a loop of some kind. you can certainly make the loop very concise, but it is impossible to test the "type" of each element without actually visiting each element. One such "clean" example could be any(isinstance(i, str) for i in my_list) Commented Mar 6, 2021 at 5:10
  • Thank you for your answer! It is valuable for me! So, would I be able to use it in the if block? Would it iterate over the list even though it is written in the if block? Commented Mar 7, 2021 at 2:54
  • 1
    any will return True or False, so yes it can be used in an if statement. the (isinstance(i, str) for i in my_list) is referred to as a generator expression, which will loop over my_list. As I said before you can't check all the elements of a list without looping over them in some way. By using any the loop will quit as soon as a single str is found, so it saves a bit of time by not continuing on after that, but if there are none, it has to check every member in the list in case the very last one is a string. Commented Mar 7, 2021 at 5:01
  • 1
    I should also point out that calling in with a list is actually running a for loop to check each element of the list to determine if the given object is "in" the list. There is just no way to avoid a for loop for this instance (whether that loop is one you write, or one happening under the hood). Commented Mar 7, 2021 at 5:41
  • Very interesting explanations, thank you! Commented Aug 19, 2021 at 15:42

4 Answers 4

6

all() stops at the first item evaluates to False. Basically:

if all(isinstance(x, (int, float)) for x in my_list):
    print("all numbers!")
else:
    print("not all number!")

And using these C-level functions instead of comprehensions should be more performant:

from itertools import repeat
if all(map(isinstance, my_list, repeat((int, float)))):
    print("all numbers!")
else:
    print("not all number!")
Sign up to request clarification or add additional context in comments.

1 Comment

Very clever approach, it is an interesting use of all( ). Thank you for your contribution!
1

I can't think of any other way to check a sequence than to check the sequence whether you do it explicitly with a for loop, or implicitly with a higher level construct. Given that, you might consider something like this if your intent is to "end the program" upon finding a non-numeric value in the list as stated.

Example:

my_list = [1,2,3,4,6,7,"8"]

for value in my_list:
    if not isinstance(value, (int, float)):
        raise TypeError(f"Expected only numeric types, found {type(value)} in sequence.")

Output:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-791ea7c7a43e> in <module>
      3 for value in my_list:
      4     if not isinstance(value, (int, float)):
----> 5         raise TypeError(f"Expected only numeric types, found {type(value)} in sequence.")

TypeError: Expected only numeric types, found <class 'str'> in sequence.

Comments

1

since you don't want to for loop use map and get types of each element in the list then you can use in to check whether the list contains sting:

seq = [0, 1, 2, 3, 4, "Hello"]

if str in map(type, seq):
    print("List contains string")

else:
    print("Accepted")

Comments

0
seq = [0, 1, 2, 3, "5", 8, 13] 

result = filter(lambda x: type(x)==str, seq)
 
print(list(result))

may be this code will filter all str type value from list

1 Comment

it is typically recommended to use isinstance rather than type(item) == some_type because it will correctly handle inheritance of derived classes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.