3

I'm new to the site and to python so I hope I'm giving all the required information. I've already searched for this question but none of the solutions seem to work for me.

I'm trying to create a function that reads some text and returns the amount of digits it contains. For example:

"It is 2012" , should return "Text has 4 digits"

If there are no digits, it should return a different message such as:

"It is Monday" , should return "Text does not contain digits"

So I wrote this:

def CountNumbers(txt):
    sum = 0

    for n in txt:
        if n.isdigit() == False:
            print ("Text does not contain digits")

        else:
            sum += 1


    print("Text has", sum, "digit(s)")


txt = str(input("Write some text: "))
(CountNumbers(txt))

The functions seem to be OK however, the prints turn out wrong, for example:

Write some text: 65
Text has 2 digit(s) #this is ok, but...

When I only input text:

Write some text: sd 
Text does not contain digits
Text does not contain digits
Text does not contain digits
Text has 0 digit(s)

When I input text and numbers (but text first):

Write some text: sd 564
Text does not contain digits
Text does not contain digits
Text does not contain digits
Text has 3 digit(s)

I know my error lies in the blocks, (I think), but I haven't figured out a way because when I use return, it stops before it finished to read the text. I've tried about 20+ different things, please help me !

Thank you !!

P.S. I need this to work as a .py and not just in the IDLE (Python Shell) window, that's why I'm writing the blocks like this.

JotaSolano
  • 65
  • 9
  • 2
    +1 for short self-contained code, and sample input/output. Multiple samples, even! Love it. – Kevin Dec 17 '12 at 20:34
  • 2
    Please remember that according to Python's naming conventions, your function should be named `count_numbers()` instead of `CountNumbers`. – pemistahl Dec 17 '12 at 20:43
  • Also, you should not name a variable `sum`, because that's the name of a built-in function. – abarnert Dec 17 '12 at 20:55
  • Thank you both so much !... I knew I was very close... this python stuff is really complicated for me hahaha... thanks ! – JotaSolano Dec 17 '12 at 20:58
  • yeah, I didn't know that cause I'm actually writing code in spanish, so when I translated the code to ask about it in here, the variable suma (spanish for sum) became sum, it was not until after that I realised that sum was also a function... it still works, but I changed it anyway :P – JotaSolano Dec 18 '12 at 00:17

4 Answers4

4

The issue is you are printing the "Text does not contain digits" message every time you encounter a non-digit character. Try moving that print statement to after the loop when you know how many characters there are:

def CountNumbers(txt):
    sum = 0

    for n in txt:
        if n.isdigit():
            sum += 1

    if sum > 0:   
        print("Text has", sum, "digit(s)")
    else:
        print ("Text does not contain digits")

txt = str(input("Write some text: "))
(CountNumbers(txt))

Edit: A couple more points towards good Python code:

  • As noted in the comments of your question, by convention, functions/methods in Python are named in lower case with underscores, i.e., count_numbers not CountNumbers.
  • Pedantic mode: you are counting the digits in the string, not numbers, so it should really be named count_digits for clarity.
  • There is a built-in Python function called sum. It is considered bad practice to shadow this function by having a variable of the same name. I'd rename your sum variable to count.
  • There is no need to surround a function call in parentheses (it doesn't do any harm, apart from making it look bad IMHO).

With these changes, your code becomes:

def count_digits(txt):
    count = 0

    for n in txt:
        if n.isdigit():
            count += 1

    if count > 0:   
        print("Text has", count, "digit(s)")
    else:
        print ("Text does not contain digits")

txt = str(input("Write some text: "))
count_digits(txt)
Blair
  • 15,356
  • 7
  • 46
  • 56
2

I just solved your codes problems:

def CountNumbers(txt):
    sum = 0

    for n in txt:
        if n.isdigit():
            sum += 1

    if sum:
        print("Text has", sum, "digit(s)")
    else:
        print ("Text does not contain digits")


CountNumbers(input("Write some text: "))
MostafaR
  • 3,547
  • 1
  • 17
  • 24
  • Your answer was really helpful, thank you A LOT ! ... I wonder, why you didn't write if sum > 0: and just if sum ... they both work, but I wonder why. I'd think that just "if sum:" is not even a condition ! haha – JotaSolano Dec 17 '12 at 21:00
  • 1
    @user1911059 - if you evaluate a number as a Boolean, it is `False` if it is zero and `True` otherwise. So in a statement like `if sum:`, it is `True` if `sum` is more than zero i.e., if there is at least one digit. – Blair Dec 17 '12 at 21:04
1

Early returns are quite alright and can greatly simplify the code:

def CountNumbers(txt):
    for n in txt:
        if not n.isdigit():
            print ("Text does not contain digits")
            return

    print("Text has", len(txt), "digit(s)")

txt = str(input("Write some text: "))
(CountNumbers(txt))

This function returns as soon as a non-digit character appears, or prints the length of the input string (which is made of nothing but digits).

You could also write that with a "generation expression" like:

def CountNumbers(txt):
    if all(char.isdigit() for char in txt):
        print("Text has", len(txt), "digit(s)")
    else:
        print ("Text does not contain digits")

txt = str(input("Write some text: "))
(CountNumbers(txt))

Now, Python functions more typically return values and let the calling code act on it. This version returns the strings and lets the "main" part of your program print the results. It also renames the function to all lowercase (Python usually uses capitalized names for classes):

def countnumbers(txt):
    if all(char.isdigit() for char in txt):
        return "Text has %d digit(s)" % len(txt)
    else:
        return "Text does not contain digits"

txt = str(input("Write some text: "))
print(countnumbers(txt))

Hmmm, not too shabby! But Python also has nifty conditional expressions like:

def countnumbers(txt):
    return ("Text has %d digit(s)" % len(txt)
        if all(char.isdigit() for char in txt)
        else "Text does not contain digits")

txt = str(input("Write some text: "))
print(countnumbers(txt))

Finally, maybe you'll want to make that into a proper module so other code can use it. Wrap the interactive part of your program like this and it will only execute if you're running it like a command line script, but not if your importing it as a module:

def countnumbers(txt):
    return ("Text has %d digit(s)" % len(txt)
        if all(char.isdigit() for char in txt)
        else "Text does not contain digits")

if __name__ == '__main__':
    txt = str(input("Write some text: "))
    print(countnumbers(txt))

If I were writing that function as part of a production system, that's pretty close to how it'd look. Notice that the logic is identical to your first attempt. The biggest difference is that this version lets Python do most of the work.

Kirk Strauser
  • 30,189
  • 5
  • 49
  • 65
  • wow this is really interesting, I'm still not familiar with this kind of writing but this does expand my comprehension a lot. Thank you ! – JotaSolano Dec 17 '12 at 21:47
  • Check comments below - `all(char.isdigit() for char in txt)` above does not work as expected - should be `all([char.isdigit() for char in txt])`. Beyond that though, the original question stated that: '"It is 2012" , should return "Text has 4 digits"'. Wouldn't short-circuiting give the wrong answer in that case? – subnivean Dec 20 '12 at 02:27
0

A slightly more pythonic reworking of the original. Personally, I find the 'list comprehension' form a little easier to read (unless it's nested):

def count_digits(txt):
    count = len([c for c in txt if c.isdigit()])

    if count > 0:
        print ("Text has", count, "digit(s)")
    else:
        print ("Text does not contain digits")
subnivean
  • 1,132
  • 11
  • 19