Book Image

Modern Python Cookbook

Book Image

Modern Python Cookbook

Overview of this book

Python is the preferred choice of developers, engineers, data scientists, and hobbyists everywhere. It is a great scripting language that can power your applications and provide great speed, safety, and scalability. By exposing Python as a series of simple recipes, you can gain insight into specific language features in a particular context. Having a tangible context helps make the language or standard library feature easier to understand. This book comes with over 100 recipes on the latest version of Python. The recipes will benefit everyone ranging from beginner to an expert. The book is broken down into 13 chapters that build from simple language concepts to more complex applications of the language. The recipes will touch upon all the necessary Python concepts related to data structures, OOP, functional programming, as well as statistical programming. You will get acquainted with the nuances of Python syntax and how to effectively use the advantages that it offers. You will end the book equipped with the knowledge of testing, web services, and configuration and application integration tips and tricks. The recipes take a problem-solution approach to resolve issues commonly faced by Python programmers across the globe. You will be armed with the knowledge of creating applications with flexible logging, powerful configuration, and command-line options, automated unit tests, and good documentation.
Table of Contents (18 chapters)
Title Page
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Creating meaningful names and using variables


How can we be sure our programs make sense? One of the core elements of making expressive code is to use meaningful names. But what counts as meaningful? In this recipe, we'll review some common rules for creating meaningful Python names.

We'll also look at some of Python's assignment statement variations. We can, for example, assign more than one variable in a single statement.

Getting ready

The core issue when creating a name is to ask ourselves the question what is this thing? For software, we'd like a name that's descriptive of the object being named. Clearly, a name like x is not very descriptive, it doesn't seem to refer to an actual thing.

Vague, non-descriptive names are distressingly common in some programming. It's not helpful to others when we use them. A descriptive name helps everyone.

When naming things, it's also important to separate the problem domain—what we're really trying to accomplish—from the solution domain. The solution domain consists of the technical details of Python, OS, and Internet. Anyone who reads the code can see the solution; it doesn't require deep explanation. The problem domain, however, can be obscured by technical details. It's our job to make the problem clearly visible. Well-chosen names will help.

How to do it...

We'll look at names first. Then we'll move on to assignment.

Choosing names wisely

On a purely technical level, Python names must begin with a letter. They can include any number of letters, digits, and the _ character. Python 3 is based on Unicode, so a letter is not limited to the Latin alphabet. While the A-Z Latin alphabet is commonly used, it's not required.

When creating a descriptive variable, we want to create names that are both specific and articulate the relationships among things in our programs. One widely used technique is to create longer names in a style that moves from particular to general.

The steps to choosing a name are as follows:

  1. The last part of the name is a very broad summary of the thing. In a few cases, this may be all we need; context will supply the rest. We'll suggest some typical broad summary categories later.
  2. Use a prefix to narrow this name around your application or problem domain.
  3. If needed, put more narrow and specialized prefixes on this name to clarify how it's distinct from other classes, modules, packages, functions, and other objects. When in doubt about prefixing, remember how domain names work. Think of mail.google.com—the name flows from particular to general. There's no magic about the three levels of naming, but it often happens to work out that way.
  4. Format the name depending on how it's used in Python. There are three broad classes of things we'll put names on, which are shown as follows:
    • Classes: A class has a name that summarizes the objects that are part of the class. These names will (often) use CapitalizedCamelCase. The first letter of a class name is capitalized to emphasize that it's a class, not an instance of the class. A class is often a generic concept, rarely a description of a tangible thing.
    • Objects: A name for an object usually uses snake_case - all lowercase with multiple _ characters between words. In Python, this includes variables, functions, modules, packages, parameters, attributes of objects, methods of classes, and almost everything else.
    • Script and module files: These are really the OS resources, as seen by Python. Therefore, a filename should follow the conventions for Python objects, using letters, the _ characters and ending with the .py extension. It's technically possible to have pretty wild and free filenames. Filenames that don't follow Python rules can be difficult to use as a module or package.

How do we choose the broad category part of a name? The general category depends on whether we're talking about a thing or a property of a thing. While the world is full of things, we can create some board groupings that are helpful. Some of the examples are Document, Enterprise, Place, Program, Product, Process, Person, Asset, Rule, Condition, Plant, Animal, Mineral, and so on.

We can then narrow these with qualifiers:

    FinalStatusDocument
    ReceivedInventoryItemName

The first example is a class called Document. We've narrowed it slightly by adding a prefix to call it a StatusDocument. We narrowed it even further by calling it a FinalStatusDocument. The second example is a Name that we narrowed by specifying that it's a ReceivedInventoryItemName. This example required a four-level name to clarify the class.

An object often has properties or attributes. These have a decomposition based in the kind of information that's being represented. Some examples of terms that should be part of a complete name are amount, code, identifier, name, text, date, time, datetime, picture, video, sound, graphic, value, rate, percent, measure, and so on.

The idea is to put the narrow, more detailed description first, and the broad kind of information last:

    measured_height_value
    estimated_weight_value
    scheduled_delivery_date
    location_code

In the first example, height narrows a more general representation term value. And measured_height_value further narrows this. Given this name, we can expect to see other variations on height. Similar thinking applies to weight_value, delivery_date and location_code. Each of these has a narrowing prefix or two.

Note

Some things to avoid: Don't include detailed technical type information using coded prefixes or suffixes. This is often called Hungarian Notation; we don't use f_measured_height_value where the f is supposed to mean a floating-point. A variable like measured_height_value can be any numeric type and Python will do all the necessary conversions. The technical decoration doesn't offer much help to someone reading our code, because the type specification can be misleading or even incorrect. Don't waste a lot of effort forcing names to look like they belong together. We don't need to make SpadesCardSuit, ClubsCardSuit, and so on. Python has many different kinds of namespaces, including packages, modules, and classes, as well as namespace objects to gather related names together. If you combine these names in a CardSuit class, you can use CardSuit.Spades, which uses the class as namespace to separate these names from other, similar names.

Assigning names to objects

Python doesn't use static variable definitions. A variable is created when a name is assigned to an object. It's important to think of the objects as central to our processing, and variables as little more than sticky notes that identify an object. Here's how we use the fundamental assignment statement:

  1. Create an object. In many of the examples we'll create objects as literals. We'll use 355 or 113 as literal representations of integer objects in Python. We might use a string like FireBrick or a tuple like (178, 34, 34).
  2. Write the following kind of statement: variable = object. Here are some examples:
      >>> circumference_diameter_ratio = 355/113>>> target_color_name = 'FireBrick'>>> target_color_rgb = (178, 34, 34)

We've created some objects and assigned them to variables. The first object is the result of a calculation. The next two objects are simple literals. Generally, objects are created by expressions that involve functions or classes.

This basic statement isn't the only kind of assignment. We can assign a single object to multiple variables using a kind of duplicated assignment like this:

>>> target_color_name = first_color_name = 'FireBrick'

This creates two names for the same string object. We can confirm this by checking the internal ID values that Python uses:

>>> id(target_color_name) == id(first_color_name)True

This comparison shows us that the internal identifiers for these two objects are the same.

Note

A test for equality uses ==. Simple assignment uses =.

When we look at numbers and collections, we'll see that we can combine assignment with an operator. We can do things like this:

>>> total_count = 0>>> total_count += 5>>> total_count += 6>>> total_count11

We've augmented assignment with an operator. total_count += 5 is the same as total_count = total_count + 5. This technique has the advantage of being shorter.

How it works...

This approach to creating names follows the pattern of using narrow, more specific qualifiers first and the wider, less-specific category last. This follows the common convention used for domain names and e-mail addresses.

For example, a domain name like mail.google.com has a specific service, a more general enterprise, and finally a very general domain. This follows the principle of narrow-to-wider.

As another example, [email protected] starts with a specific destination name, has a more general enterprise, and finally a very general domain. Even the name of destination (PacktPub) is a two-part name with a narrow enterprise name (Packt) followed by a wider industry (Pub, short for publishing). (We don't agree with those who suggest it stands for Public House.)

The assignment statement is the only way to put a name on an object. We noted that we can have two names for the same underlying object. This isn't too useful right now. But in Chapter 4, Built-in Data Structures – list, set, dict we'll see some interesting consequences of multiple names for a single object.

There's more...

We'll try to show descriptive names in all of the recipes.

Note

We have to grant exceptions to existing software which doesn't follow this pattern. It's often better to be consistent with legacy software than impose new rules even if the new rules are better.

Almost every example will involve assignment to variables. It's central to stateful object-oriented programming.

We'll look at classes and class names in Chapter 6, Basics of Classes and Objects; we'll look at modules in Chapter 11,Application Integration.

See also

The subject of descriptive naming is a source of ongoing research and discussion. There are two aspects—syntax and semantics. The starting point for thoughts on Python syntax is the famous Python Enhancement Proposal number 8 (PEP-8). This leads to use of CamelCase, and snake_case names.

Also, be sure to do this:

>>> import this

This will provide more insight into Python ideals.

Note

For information on semantics, look at the legacy UDEF and NIEM Naming and Design Rules standards (http://www.opengroup.org/udefinfo/AboutTheUDEF.pdf). Additional details are in ISO11179 (https://en.wikipedia.org/wiki/ISO/IEC_11179), which talks in detail about meta-data and naming.