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:
| 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.
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.
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.