Frequently Asked Questions about Python terms and syntax

One of the best things about Python is its elegant and intuitive syntax. However, there were times where I would come across some terms or syntax that I wasn't readily sure about. So I've decided to write a quick-fire post of explanations about some of these to help people who are starting out to ramp up their Python knowledge. Hopefully, you'll find it useful. If there's anything else you think might be worth adding to this list, feel free to leave it in the comments.

Let's get started with some of the basics of Python project structure.

What are modules?

You may have heard people talking about a Python module. Well, a module is essentially a python (.py) file. Below is a simple example below of an example.py module. Typically, you'd use a module as a file to contain a bunch of functions or a Class and it's methods. Here's an example of a basic Python module containing a simple greet() function.

# example.py
def greet(name):    print('Hi ' + name)

Below is how you can import a module. This code starts the Python shell from the command prompt, imports the example.py module and calls the greet function which prints out a greeting.

$ python
>>> import example
>>> example.greet('Wendy')
>>> Hi Wendy

It's generally considered good practice for readability to import a module and then reference the function within that module using dot notation, i.e: example.greet('Wendy') so that people can easily see which module the function belongs to.

However, in some cases it may be better for readability to import specific functions or classes from a module so that you don't need to reference the module, for example so that you wouldn't need to write something like this:

import datetimecurrent_time = datetime.datetime.now()

The above example may seem a bit verbose, especially in the context of more code. The datetime module is also quite well known so in this case it may be better to import the datetime class from the datetime module specifically so that you don't have to provide the module name when referencing it.

from datetime import datetimecurrent_time = datetime.now()

Use your discretion for what you think may appear more readable to other people.

What are packages?

You might have also heard of a Python package. A package is essentially a folder or directory that contains a bunch of modules and an __init__.py file. Consider the following project folder structure below.

project    
├── package    
│   ├── __init__.py    
│   ├── example.py    
└── project.py

You would now be able to import your package into your project.py code and call the greet() function like this:

# project.py
from package import example


example.greet('Millie')

What is init.py?

As mentioned above, having __init__.py in a folder will make Python treat the directory as a package. Also note that Python will execute any code in the __init__.py file when the package is imported. So you could use this to do any setup when your module is imported if you wanted to.

What are docstrings?

A docstring is a comment that you can put in certain parts of your Python code to provide convenient reference documentation for modules, classes and methods.

"""A module's docstring"""


class MyClass(object):    
    """docstring for MyClass"""

    def my_method(self):    
        """docstring for my_method"""


def my_function():    
    """docstring for my_function"""

IDEs will generally detect and display docstrings when users hover over items. So docstrings are a useful way to give a short explanation to developers about how a modules, classes or methods can be used.

What are *args and **kwargs?

Essentially, the * and ** operators just expand an iterable (list, tuple, set etc.) or dictionary, respectively, into a function's arguments or keyword arguments. Using the naming *args and **kwargs is just convention. In theory, you can use whatever naming you want with the operators. Here's an example of how *args can be used:

def print_things(*args):
    for item in args:
        print item

print_things('table', 'chair', 'lamp', 'bookshelf')

and here's a slightly different example showing how we can unpack a dictionary into keyword arguments for a function

def print_profile(name=None, bio=None):
    if bio:
        print(name + ": " + bio)
    else:
        print(name)

user_1 = {'name': 'Tyler', 'bio': 'I like hiking'}
user_2 = {'name': 'Jess'}
users = [user_1, user_2]

for user in users:
   print_profile(**user)

The last thing to note about *args and **kwargs is that if you are going to use any combination of them in a function with normal arguments, they need to be in the following order:

def my_function(arg, *args, **kwargs):
    # Do something

If you found this post helpful, you might be interested in reading How to Structure a Python Project.