Introduction to Python Programming Language

 

Python is a high-level, interpreted programming language known for its emphasis on code readability and simplicity. This pretty much summarizes the key characteristics of the language, and explains why it stood out among other programming languages recently.

In computer science, a high-level programming language refers to one that provides strong abstraction from the underlying hardware details. This means that programmers can focus on logic and functionality of their programs without needing to worry about the specific instructions that the computer’s processor will execute. Python is one such language. It has human-readable syntax, hides complicated details (e.g., memory management), and is completely portable across different types of operating systems, including Windows, Mac, and Linux, with no code modification.

It is also an interpreted language. This further sets Python apart from other high-level languages like Java or C. When you install Python, a special program called the Python interpreter is bundled. This program directly translates Python into machine code without compilation. This contrasts with compiled languages which requires the entire code to be converted into machine code before execution. Instead of compiling the entire set of code as a whole and generating executable file, Python executes the code line by line at runtime, making it more flexible and interactive.

Python’s syntax is designed to be intuitive and straightforward. It employs elements from natural languages. For example, in Python, code indentation not just organizes the code but also defines the level of the code. In contrast to many other languages that use symbols like curly brackets or keywords to denote code blocks, Python uses different levels of indentations to indicate hierarchy and scope. Its syntax is also very simple. For example, to print out “Hello, World!” using Java programming language:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}

The same result can be done by the running Python code below:

print('Hello World!')
## Hello World!

We can clearly see that Python’s syntax is much simpler than that of Java.

All these defining characteristics of Python have been driven its increasing popularity among programmers. Its simple syntax and interpreted nature enables developers to quickly prototype their ideas. Particularly, in the field of data science and machine learning, where frequent adjustments are required, Python allows for quicker development cycle, as you can test code changes immediately without compilation.

Basic Building Blocks of Python

Python’s syntax is designed to be readable and easy to learn. Here’s a breakdown of its elements:

  • Literals: Values that are directly written in the Python code scripts.
  • Identifiers: Python is an object oriented programming (OOP) language and nearly everything in Python, including literals, variables, or functions, is considered as an object. Each of these objects has a given name, called identifier.
    • Variables: A variable is a name that refers to a literal value. In Python, variables do not require explicit declaration and are dynamically typed,“ meaning you can reuse the same variable name for different object; reassignment is allowed during program execution.
    • Functions: A function is a block of reusable code whenever it is called. Python supports regular functions (defined with the def keyword), lambda functions (defined with lambda keyword), as well as many built-in functions for common tasks.
    • Modules and Packages: A module is a .py file that contains related functions and classes. A package is an organized collection of modules and/or other sub-packages. Both can be imported and used in a Python program for execution.
  • Data Types: Python supports several native types like int, floats, strings, lists, tuples, sets, dictionaries, and more. These types determine the kind of operations you can perform on variables.
  • Operators: Symbols that perform operations on variables and literals.
  • Reserved Words: These have some predefined meanings and cannot be used as an identifier. Reserved words are part of the Python syntax and serve specific purpose within the language. Examples include if, else, while, for, def, and class.
  • Indentation: In computer programming, indentation refers to the use of spaces or tabs at the beginning of code lines to indicate how they are structured. Particularly, in Python, indentation is not just for readability; it serves as a syntactical element to define the scope of code blocks. For each level, you can use either a tab or four spaces1. Note that mixing spaces and tabs to indicate multiple indent levels within a single block is not allowed.
  • Comments: Non-executable lines in code, helping with documentation. They start with # for single-line comments, and triple quotes (''' or """) can be used for multi-line comments.

Operators combined with variables and/or literals are called expressions. Objects placed on left and right sides of the operators are evaluated into a single value, containing the outputs from the supposed calculations. For example:

  • 3 + 4 is evaluated into a single number 7.
  • "Hello, " + "World!" is evaluated into a single string "Hello, World!".
  • True and False is evaluated into False.

When Python expressions are combined with some other expressions, reserved words, and/or variables, it becomes a Python statement,2 which represents a complete line of code performing an operation. For example:

  • my_var = 3 + 4
  • print("Hello, " + "World!")
  • if True and False: print("Won't be printed")

In the examples, the + operator adds 4 to 3 and = operator assigns the calculated value into a variable named my_var. Similarly, print("Hello, " + "World!") is a statement that takes the string output from the + operation. and passes it to the print() function to display the result. Observe that the same operator (+) works differently, depending on which context it is used: when applied to numeric literals, it sums the values, while it performs concatenations when applied to strings.

A Python function refers to a collection of related Python statements, grouped under an indentation. For example:

def add_nums(a, b):
    result = a + b
    return result

This function takes two parameters a and b, adds them together, and returns the result. By grouping the Python statements as a function, you can reuse them whenever needed.

Variable Assignments in Python

In Python, variable assignments can be done using the assignment operator (=). It assigns the objects placed on its right side into a name specified on its left side. Unlike other programming languages, Python do not require explicit declaration of a variable with its data type, Instead, the Python interpreter infers the data type dynamically based on the contexts. For example, in Java, to declare a variable you should also specify the data type (e.g., int x = 5;) and the variable cannot change its type once it has been declared. This means that if you declare a variable as an integer, you cannot later assign a string or other data type to it. However, in Python, the data type of a variable is flexible, and it can change during runtime3:

x = 5  # Python infers that x is an integer
y = "Hello"  # Python infers that y is a string

In this example, Python allows x to change from an integer to a string, which is not possible statistically typed languages like Java.

This property often leads to some unexpected behaviors. For example:

x = 5
y = 6

add_nums(x, y)

x = 'Hello" # Now x is reassigned as an integer

add_nums(x, y)
## unterminated string literal (detected at line 6) (<string>, line 6)

Nevertheless, dynamic typing of Python makes its syntax concise and readable compared to that of other programming languages.

Naming Rules and Conventions

To be a valid name for a variable, it must adhere to the following naming rules:

  • Start with a letter or an underscore(_): Variable names cannot begin with a number.
    • Valid: _my_var, myVar
    • Invalid: 1st_var
  • Contain only letters, numbers, or underscores: Special characters like @, #, !, or spaces are not allowed.
    • Valid: my_var, var123
    • Invalid: my-var, my var
  • Cannot use reserved words: You cannot assign Python’s reserved words to a variable.
    • Invalid: for, if

In addition to the naming rules, Although not strictly enforced by Python, following these conventions makes your code more readable and maintainable:

  • Use descriptive names: Choose names that clearly indicate the purpose of the variable. This practice also helps avoiding errors caused from the dynamic typing.
    • Good: student_count (should be an integer), total_price (should be a float)
    • Poor: data
  • Follow snake_case: Use lowercase letters with underscores to separate words.
    • Example: employee_name, max_value
  • Constants in UPPERCASE: Python do not support a distinct constant and all variables are dynamically typed. So, if your variable is intended to act like a constant through out your program, use all uppercase letters
    • Example: UPPER_LIMIT = 100
  • Avoid single-character names: Except for loops, avoid using single leters for descriptive variables.
    • Good: index, counter
    • Poor: x, y
  • Avoid names starting with an underscore unless necessary: Variables starting with _ are typically used for private or special purposes.

All these conventions aim to make code “Pythonic,” a term that embodies writing clean, readable, and efficient code that adheres to Python’s philosophy and best practices.

import this
## The Zen of Python, by Tim Peters
## 
## Beautiful is better than ugly.
## Explicit is better than implicit.
## Simple is better than complex.
## Complex is better than complicated.
## Flat is better than nested.
## Sparse is better than dense.
## Readability counts.
## Special cases aren't special enough to break the rules.
## Although practicality beats purity.
## Errors should never pass silently.
## Unless explicitly silenced.
## In the face of ambiguity, refuse the temptation to guess.
## There should be one-- and preferably only one --obvious way to do it.
## Although that way may not be obvious at first unless you're Dutch.
## Now is better than never.
## Although never is often better than *right* now.
## If the implementation is hard to explain, it's a bad idea.
## If the implementation is easy to explain, it may be a good idea.
## Namespaces are one honking great idea -- let's do more of those!

Augmented Assignments

In Python, augmented assignments are shorthand operators that combine an operation with assignment. They allow you to modify a variable by performing an operation and then reassigning the result to the same variable. These operators can be used to simplify code and improve readability, especially when performing arithmetic or other operations on variables.

Common augmented assignment operators include:

  • +=: Add and assign
  • -=: Subtract and assign
  • *=: Multiply and assign
  • /=: Divide and assign
  • //=: Floor divide and assign
  • %=: Modulus and assign
  • **-: Exponentiate and assign

For example:

x = 10
x += 5  # x = x + 5, so x becomes 15
print("Current value of x is", x)  
## Current value of x is 15
y = 20
y *= 3  # y = y * 3, so y becomes 60
print("Current value of y is", y)  
## Current value of y is 60
z = 100
z /= 4  # z = z / 4, so z becomes 25.0 (result is a float)
print("Current value of z is", z)  
## Current value of z is 25.0

Native Data Types in Python

Python has a rich set of native data types to represent different kinds of data. Here’s an overview:

Basic Data Types

Basic data types are used to represent individual values like numbers, Booleans, or null-like data values. They are atomic and cannot be broken into smaller data elements. Basic data types are also immutable, meaning their values cannot be changed after they are created. Instead, any operation that “modifies” a basic data type will create a new object with the updated value.

  • Numbers
    • int: Represent integers (e.g., 42, 7). Constructor for the type is int(value=0). For example: int("42") \(\rightarrow\) 42
    • float: Represents floating-point numbers (e.g., 3.14, -0.001). Constructor for the type is float(value=0.0). For example: float("3.14") \(\rightarrow\) 3.14
    • complex: Represents complex numbers with real and imaginary parts (e.g., 1+2j). Constructor for the type is complex(real=0, imag=0). For example: complex(1, 2) \(\rightarrow\) (1+2j).
  • Boolean (bool): Represents Boolean values (True or False). Constructor for the type is bool(value). For example: bool(0) \(\rightarrow\) False.
  • NoneType (None): Represents the absence of a value. Constructor for the type is not applicable; only one instance exists for the type: None.

Sequence Data Types

Sequence types represent ordered collection of elements. These types allow indexed access, slicing, and iteration. They can store atomic values like basic data types we saw earlier or composite data.

  • Strings (str): Immutable sequences of Unicode characters. Constructor for the type is str(object=''). For example: str(42) \(\rightarrow\) "42"
  • Lists (list): Mutable ordered collections of items. Constructor for the type is list(iterable=[])4. For example: list("abc") \(\rightarrow\) ['a', 'b', 'c'].
  • Tuples (tuple): Immutable ordered collections of items. Constructor for the type is tuple(iterable = ()). For example: tuple([1, 2, 3]) \(\rightarrow\) (1, 2, 3).
  • Ranges (range): Represents a sequence of numbers. Constructor for the type is range(start, stop[, step]). For example: range(0, 10, 2) \(\rightarrow\) 0, 2, 4, 6, 8

For the sequence data types, you can index to access individual elements contained in the object. Python uses zero-based indexing, meaning the first element in a sequence has an index of 0. For example:

my_str = "Hello, World!"
print(my_str[0])
## H

Python allows you to use negative indices to access elements from the end of a sequence. -1 refers to the las t element, -2 to the second last, and so on. For example:

my_list = [10, 20, 30, 40]
print(my_list[-1]) # Last element: 40
## 40
print(my_list[-2]) # Second last element: 30
## 30

You can retrieve multiple elements using slicing, which specifies a range of indices:

sequence[start:stop:step]

Where:

  • start: The index of the first element to include (default is 0).
  • stop: The index where slicing ends (exclusive).
  • step: The interval between elements (default it 1).

For example:

my_list = [10, 20, 30, 40, 50]
print(my_list[1:4]) # Elements from index 1 to 3: [20, 30, 40]
## [20, 30, 40]
print(my_list[:3]) # First three elements: [10, 20, 30]
## [10, 20, 30]
print(my_list[::2]) # Every second element: [10, 30, 50]
## [10, 30, 50]
print(my_list[::-1]) # Reversed list: [50, 40, 30, 20, 10]
## [50, 40, 30, 20, 10]

Set Data Types

Set types represent unordered collections of unique elements. They are used for mathematical set operations and ensuring data uniqueness.

  • Sets (set): Mutable collections of unique, unordered elements. Constructor for the type is set(iterable=[]). For example: set([1, 1, 2, 3]) \(\rightarrow\) {1, 2, 3}.
  • Frozen Sets (frozenset): Immutable sets that can be used as dictionary keys or elements of other sets. Constructor for the type is frozenset(iterable=[]). For example: frozenset("abc") \(\rightarrow\) frozenset({'a', 'b', 'c'}).

Mapping Data Types

Mapping types store key-value pairs for fast lookups. Keys must be unique and hashable.

  • Dictionaries (dict): Mutable collections of key-value pairs. Constructor for the type is dict(mapping_or_iterable). For example: dict([("name", "Alice"), ("age", 25)]) \(\rightarrow\) {'name': 'Alice', 'age': 25}.

Binary Data Types

Binary types are designed to handle raw binary data. They are useful for low-level operations such as file handling or network protocols.

  • Bytes (bytes): Immutable sequences of bytes. Constructor for the type is bytes(source[, encoding[, errors]]). For example: bytes("hello", "utf-8") \(\rightarrow\) b'hello'.
  • Byte Arrays (bytearray): Mutable sequences of bytes. Constructor for the type is bytearray(sequence[, encoding[], errors]]). For example: bytearray("hello", "utf-8") \(\rightarrow\) bytearray(b'hello')
  • Memory Views (memoryview): Provides a view of another binary data type without copying data. Constructor for the type is memoryview(obj). For example: memoryview(b'hello').

To check the data type of a variable or any other Python object, you can use the type() function. This function is frequently employed for the purpose of debugging, along with the print().

type(True) # Output: Boolean
## <class 'bool'>
type(5) # Output: integer
## <class 'int'>
type(12.345) # Output: float
## <class 'float'>
type('12.345') # Output: string
## <class 'str'>
type(print) # Output: builtin_function_or_method
## <class 'builtin_function_or_method'>
type(list) # Output: type
## <class 'type'>

The isinstance() function, on the other hand, checks whether an object belongs to a specific data type and returns True or False. This function is particularly useful for validating inputs or conducting unit tests.

isinstance(-11, int) # Checks if -11 is an instance of int
## True
isinstance(3.14, int) # Checks if 3.14 is an instance of int
## False

  1. However, Google’s Python style guide recommends using four spaces. This ensures consistent formatting across different editors and environments.↩︎

  2. The distinction between expressions and statements could be little ambiguous. For example, you can also think of 3 + 4 as a statement. This is called an expression statement, which evaluates and executes the expression. In essence, expressions are code snippets used to apply an operator and calculate a value, while statements are complete instructions that perform actions of a program.↩︎

  3. In Python, a variable can be mutable or immutable depending on its data type. Variables with mutable data types can be changed in place, meaning their content can be modified without creating a new object. Examples include lists, dictionaries, and sets. On the other hand, variables with immutable data types cannot be altered once created. Any modification attempt results in the creation of a new object. So, technically, for immutable data types like int, the created literal object cannot be modified. If you reassign the same variable name to the object, Python creates a new object and associate the variable name with it. You can verify this behavior using the id() function, which returns the unique identifier of an object in the computer memory. If you apply the function to an immutable object, before and after reassignments, you’ll notice that the object IDs differ. This is because reassignment creates a new object rather than modifying the existing one. For mutable data types like list, however, the object itself can be modified without creating a new one.↩︎

  4. In Python, an iterable is any object capable of returning its members one at a time, allowing it to be looped over. Common examples include lists, strings, tuples, dictionaries, sets, and even file objects.↩︎

Post a Comment

0 Comments