Defining and Calling Functions

In most programming languages, you cannot go far without defining and calling your own functions. In Python, you define a function with the def keyword:

just_enough_python/functions.py
 def​ ​welcome​(user):
  PASSWORD = ​"1234"
  message = ​"Hi, ​​%​​s! Your new password is ​​%​​s"​ % (user, PASSWORD)
 return​ message

This function generates a password for a new user. (Admittedly, the default password isn’t the most secure—but hey, at least it’s popular.) Then it composes a welcome message, and returns the message to the caller.

Pythonically, you don’t need to delimit the function’s body with brackets—you just indent it. Also, being Python dynamically typed, you don’t need to specify the type of the user parameter, or the type of the function’s return value. Taken together, these features make for a very concise function declaration.

Once you have a function defined, you can call it:

 welcome(​"Roberto"​) ​# => 'Hi, Roberto! Your new password is 1234'

Python has a few different flavors of function arguments. Let’s look at them.

 

Named Arguments

You can use named arguments, also called keyword arguments, to make a function call easier to read. Let’s look at an example.

Assume that your boss just saw the welcome function from the previous section, and he really liked it—but he’s concerned that the password isn’t very secure. He proposes a solution: add a secure argument to the function. If secure is True, then the function should generate a more secure password.

Here is the updated welcome function:

 def​ ​welcome​(user, secure):
 if​ secure:
  PASSWORD = ​"123456"
 else​:
  PASSWORD = ​"1234"
 return​ ​"Hi, ​​%​​s! Your new password is ​​%​​s"​ % (user, PASSWORD)

We don’t mess around with security here, buddy. Now we can call the function with the secure flag on:

 welcome(​"Roberto"​, True) ​# => Hi, Roberto! Your new password is 123456

Note, however, that the function call here has a readability issue: if you don’t know what that True argument means, then you have no way of finding out, short of looking at the function definition. It would be nice to show clearly that True is the value of the secure argument. You can do that by using named arguments:

 welcome(​"Roberto"​, secure=True) ​# => Hi, Roberto! Your new password is 123456

Now the call is more readable. As an added bonus, named arguments allow us to change the order of the arguments in the call—although I’ll leave it to you to decide whether that’s a good idea in general:

 welcome(secure=False, user=​"Mike"​) ​# => Hi, Mike! Your new password is 1234

We’re not quite done with function arguments yet. There is one last useful feature related to them, and we use it a lot in this book.

Default Arguments

The boss just asked for a few more changes to the security system. He wants the function to work even if we don’t provide the user’s name. Besides, he wants the password to be secure by default, unless the caller specificies otherwise.

We can implement both features by specifying the arguments’ default values in the function definition:

 def​ ​welcome​(user=​"dear user"​, secure=True):
 if​ secure:
  PASSWORD = ​"123456"
 else​:
  PASSWORD = ​"1234"
 return​ ​"Hi, ​​%​​s! Your new password is ​​%​​s"​ % (user, PASSWORD)

Now we can skip one or both arguments, and they’ll take their default values:

 welcome() ​# => Hi, dear user! Your new password is 123456

You can even mix and match named arguments and default arguments:

 welcome(secure=False) ​# => Hi, dear user! Your new password is 1234

With that, you know everything you need about Python functions and their arguments. And just to be clear: I do not recommend this code to generate passwords in production. You never know… it might contain non-obvious security bugs.