feedthemachine
feedthemachine

Reputation: 620

python `else` doesn't work as expected

def greet(language):
    database = {'english': 'Welcome',
                'czech': 'Vitejte',
                'danish': 'Velkomst',
                'welsh': 'Croeso'}
    for k, v in database.items():
        if language == k:
            return v
        # else: return('Welcome')

print(greet('czech'))
> Vitejte

If I uncomment else: return('Welcome') (so if the greeting language is not in the list) I expect to receive 'Welcome' but it returns 'Welcome' no matter if I enter the existing or non-existing language.

I had also tried elif language =!= k but it appeared to work in the same unwanted fashion

Upvotes: 0

Views: 149

Answers (6)

Kumar
Kumar

Reputation: 143

Whatever you have mentioned is expected behaviour only , why because DICTIONARY is a un-ordered collection of objects.

whenever you do dict.items() it may iterate in any order,consider your example itself:

def greet(language):
database = {'english': 'Welcome','czech': 'Vitejte','danish': 'Velkomst',
            'welsh': 'Croeso'}

for k, v in database.items():
    print "k,v :",k,v       --> it may print you in any order 

output:
       Combination 1:

       1) english': 'Welcome 2) danish': 'Velkomst 3) czech': 'Vitejte
       4) welsh': 'Croeso

       Combination 2:

       1) welsh': 'Croeso  2)  english': 'Welcome 3) czech': 'Vitejte
       4) danish': 'Velkomst

       and few more combinations will yield .....

So, In your example your first iteration is other than czech that is the reason your code is always returning Welcome.

To avoid that, either you can go with dict.get() or simply track a variable as below:

def greet(language):
var = 0                            -> intialized var with 0
database = {'english': 'Welcome',
            'czech': 'Vitejte',
            'danish': 'Velkomst',
            'welsh': 'Croeso'}
for k, v in database.items():

    if k == language:
        var = 1                    -> if enterd in loop assign var = 1 
        return v

if (var != 1):
   return('Welcome')               -> if above compa'ion fails returns welcome

print(greet('czech'))

Vitejte

print(greet('zabcczech'))

Welcome

Upvotes: 0

void
void

Reputation: 2642

Take a look at this SO post you will get an idea about what is the fastest way to check if a key is in dictionary.

So in your case I would say this is the fastest way to check

def greet(k):
    database = {'english': 'Welcome',
                'czech': 'Vitejte',
                'danish': 'Velkomst',
                'welsh': 'Croeso'}
    if k in database:
        return(database[k])
    else:
        return('Welcome')
print(greet('welsh'))

output:

Croeso

But for:

def greet(k):
    database = {'english': 'Welcome',
                'czech': 'Vitejte',
                'danish': 'Velkomst',
                'welsh': 'Croeso'}
    if k in database:
        return(database[k])
    else:
        return('Welcome')
print(greet('tamil'))

output:

Welcome

Upvotes: 0

JyotiGrover
JyotiGrover

Reputation: 93

I have modified code and attached output as well:

def greet(language):
    database = {'english': 'Welcome',
                'czech': 'Vitejte',
                'danish': 'Velkomst',
                'welsh': 'Croeso'}
    for k in database.keys():

        if language == k:
            return database[k]

    return('Welcome')


print(greet('english'))
print(greet('czech'))
print(greet('welsher'))
print(greet('danish'))
print(greet('welsh'))
print(greet('hindi'))

Output : Welcome Vitejte Welcome Velkomst Croeso Welcome

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476547

See it like this, the for loop will enumerate over the items.

Let's assume the first item the .items() fetches is 'english': 'Welcome'. Now if the language is not English, then the if will fail, and so the else part is executed an 'Welcome' is returned. Only if the first item enumerated is indeed the correct language, your program will return that value.

Nevertheless you make things too complicated, you can use dict.get(..) with a fallback value:

def greet(language):
    database = {'english': 'Welcome',
                'czech': 'Vitejte',
                'danish': 'Velkomst',
                'welsh': 'Croeso'}
    return database.get(language,'Welcome')

This will also boost performance: your original program had O(n) time complexity whereas a lookup on average on a dictionary is done in O(1) time.

Upvotes: 6

Moses Koledoye
Moses Koledoye

Reputation: 78536

That's because the return statement when executed in the first branching to else hijacks control from the for, exiting the function. You can, for example, move the else as part of the for instead; indicating 'Welcome' should only be returned when the for is exhausted cleanly:

...
for k, v in database.items():
    if language == k:
        return v
else: 
    return 'Welcome'

Or use the dictionary's get method to return a default:

...
return database.get(lang, 'Welcome')

Upvotes: 3

user94559
user94559

Reputation: 60133

You want this instead:

def greet(language):
    database = {'english': 'Welcome',
                'czech': 'Vitejte',
                'danish': 'Velkomst',
                'welsh': 'Croeso'}
    for k, v in database.items():
        if language == k:
            return v

    # Return this only if none of the items matched.
    return('Welcome')

As your code currently stands, it only ever checks the first item in the dictionary. If that key matches, it returns the appropriate value. Otherwise, it returns "Welcome," but it never moves on to the second item.

In my code, it checks all of the items and returns the right value as soon as it finds a match. Only if it fails to find a match does it return "Welcome."

Incidentally, this is an even simpler version of the code:

def greet(language):
    database = {'english': 'Welcome',
                'czech': 'Vitejte',
                'danish': 'Velkomst',
                'welsh': 'Croeso'}
    return database.get(language, 'Welcome')

dict.get lets you do a dictionary lookup and use a default value if the item is not found.

It's basically short-hand for this (but dict.get is preferred):

if language in database:
    return database[language]
else:
    return 'Welcome'

Upvotes: 7

Related Questions