Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

optional argument Python

Have to write some code that defines a function that will work with two or three arguments.

The function should take three parameters:

  • temperature, a float
  • weather, a string
  • is_celsius, a boolean

The function should return True if temperature is below freezing (32 if is_celsius is False, 0 if is_celsius is True) or if weather is "snowy". Otherwise, it should return False.

Note, however, that is_celsius should be an optional argument. If the function call does not supply a value for is_celsius, assume it is True.

I wrote this

def snowed_in(temperature, weather, **cels):
    if weather =="snowy":
        return True
    elif weather=="sunny":
        if 'is_celsius = False' in cels:
            if temperature<32:
                return True
    elif 'is_celsius = True' in cels:
        if temperature<0:
            print ('ad')    
            return True
    elif 'is_celsius = True' not in cels:
        if temperature<0:
            return True
    else:
        return False

and for the following calls

print(snowed_in(15, "sunny")) #Should print False
print(snowed_in(15, "sunny",is_celsius = False)) #Should print True
print(snowed_in(15, "snowy",is_celsius = True)) #Should print True

I'm getting

None
None
True

Can someone help me find what's wrong with my code?

like image 1000
tito_zako Avatar asked Mar 02 '23 06:03

tito_zako


2 Answers

This is not a situation where it makes sense to use **kwargs - that would normally be used for wrapper functions.

You should simply do something like this to declare is_celsius explicitly as an optional argument:

def snowed_in(temperature, weather, is_celsius=True):
    if weather == "snowy":
        return True
    elif is_celsius:
        return temperature < 0
    else:
        return temperature < 32

However, if there is some good reason to capture optional arguments in a dictionary (maybe you also need to pass it to a function that you are wrapping), then you could extract the relevant parameter using get with any default value (otherwise it will default to None):

def snowed_in(temperature, weather, **kwargs):
    if weather == "snowy":
        return True
    elif kwargs.get('is_celsius', True):
        return temperature < 0
    else:
        return temperature < 32
like image 73
alani Avatar answered Mar 29 '23 23:03

alani


There are a few things here, so let me post an edit to your code and step through the changes with you :)

def snowed_in(temperature, weather, cels=True):
    if weather =="snowy":
        return True
    elif weather=="sunny":
        if not cels:
            if temperature<32:
                return True
    elif cels:
        if temperature<0:
            print ('ad')    
            return True
    else:
        return False

Boolean expressions

You input is_celsius as a boolean but evaluate it as a string which is more than a little odd.

Instead of trying to match a specific string i.e. 'is_celsius = True' in cels:, you can just check the state of the boolean 'cels' ie if cels:

Default arguments

If the function call does not supply a value for is_celsius, assume it is True.... python function arguments can have default values.

So using cels=True is preferable to **cels for your desired behaviour.

Now, cels=True will be passed to the function if cels is not specified in the function call.

Syntax

If you're new to Python check out PEP8. The point here is that you should try not to have spaces between a variable name, and it's value, in the function arguments i.e cels=True not cels = True.

Indentation

I'm assuming this was an artifact of you copy pasting your code. But! Note that indentation is super important in python. Note the difference between your code and my example above... it's good practice to ensure your code has proper indentation if you're copy pasting it into to stack overflow / somewhere else. Makes it easier for others to read!

Good luck out there!

like image 38
mackdelany Avatar answered Mar 30 '23 00:03

mackdelany