-1

In python 3.6, I'm trying to get a string to print with a delay between characters and a longer delay for punctuation at the end of sentences to pseudo-simulate spoken English. Here is my code. My problem is that I get the delay between characters, but I don't get the longer delay between sentences.

import time
import sys


def delay_print(s):
    for c in s:
        if c != "!" or "." or "?":
            sys.stdout.write(c)
            # If I comment out this flush, I get each line to print
            # with the longer delay, but I don't get a char-by char 
            # delay
            # for the rest of the sentence.
            sys.stdout.flush()
            time.sleep(0.05)
        elif c == "!" or "." or "?":
            sys.stdout.write(c)
            sys.stdout.flush()
            time.sleep(3)


delay_print( """
    Hello.
    I want this to have an added delay after sentence-ending 
    punctuation?
    But I also want it to have a shorter delay after each character 
    that isn't one of those chars.
    This is supposed to mimic speech patterns. Like if you've ever 
    played SNES Zelda: A Link to the Past.
    Why isn't this code doing what I want it to?.
    What I've written is broken and I don't know why!
""")
sr71shark
  • 11
  • 4

3 Answers3

2

Your or clause isn't doing what you think it's doing. The first one checks if any of these three things is True:

  1. character != "!"
  2. bool(".")
  3. bool("?")

Note that 2 and 3 are always true.

If statements short circuit evaluate. If the character input were ., it would check condition 1 and find it false. Then it would include condition 2 in the evaluation False or ".". Since "." is always true, it short circuits and returns "." which evaluates to true. Try it yourself, type False or "." into the interpreter, you'll find it returns ".".

Personally, I would do this with a set implementation like this:

if c not in {"!", ".", "?"}:
sage88
  • 4,104
  • 4
  • 31
  • 41
  • Please refrain from answering obvious duplicates. If you think you can add a better answer to the canonical question at the end of the chain of duplicates, of course, please do that. – tripleee Feb 26 '19 at 06:18
  • That fixed my issue! I knew that I just wasn't understanding the proper way this should be written. Thanks for the reply! – sr71shark Feb 26 '19 at 06:28
  • Just to make sure you understand why what you had was wrong, consider the syntax the way you had it, but corrected to have the desired logic: `if c != "!" or c != "." or c != "?":`. To answer your other question, in any version of python a non-empty string is True. @tripleee trying to be nice since he's new, but I'll refrain. Also the SO you linked as a duplicate is also a duplicate :D – sage88 Feb 26 '19 at 06:33
  • @sage88 Oof my mistake, thanks to your explanation, I see how this is exactly the same issue in the linked duplicates. I appreciate you taking the time to help me get it. – sr71shark Feb 26 '19 at 06:39
  • @sr71shark Happy to help. Going to delete this answer. Which apparently I cannot do because it's been accepted. – sage88 Feb 26 '19 at 06:40
0

Both of the conditions that you are testing will always evaluate to True no matter what the value of c:

>>> letter == "!" or "." or "?"
'.'
>>> letter = "a"
>>> if letter != "!" or "." or "?":
    print("not punctuation")


not punctuation
>>> if letter == "!" or "." or "?":
    print("punctuation")


punctuation

As another user suggest it may make more sense for you to change your tests to:

>>> letter in "!.?"
False
>>> letter not in "!.?"
True

Also, on a more stylistic note I would consider using a random delay between letters to make it even more organic feeling.

import random

...

delay = random.random() + 2.5
sleep(delay)
lvrf
  • 188
  • 2
  • 8
0

Give this a shot! Your first if statement needs to use 'and' instead of 'or', because it was always True.

def delay_print(s):
    for c in s:
        if c != "!" and c != "." and c != "?":
            sys.stdout.write(c)
            sys.stdout.flush()
            time.sleep(0.05)
        else:
            sys.stdout.write(c)
            sys.stdout.flush()
            time.sleep(3)
Kurt
  • 31
  • 1
  • 2