Fundamental Python
Introduction to Python and its history
Python is a high-level, interpreted, and general-purpose programming language that is easy to learn and use. Created in the late 1980s by Guido van Rossum, Python is known for its simple and elegant syntax, readability, and ease of use. It is an open-source language, which means that it is free to use and distribute, and has a large and active community of developers constantly contributing to its development and maintenance.
One of Python's key features is that it is a multi-paradigm language, meaning that it supports several programming paradigms such as object-oriented, functional, and procedural programming. This makes it a versatile language that can be used for a wide range of tasks and applications, from web development and data analysis to machine learning and artificial intelligence.
Python's standard library is also very rich, providing a wide range of modules and functions that cover many aspects of programming, such as file handling, regular expressions, and data structures. Additionally, there are many third-party libraries and frameworks available that extend Python's capabilities even further.
History of Python:
Python was first developed by Guido van Rossum in the late 1980s, and its first version (Python 0.9.0) was released in February 1991. The language was named after the popular British comedy group Monty Python, and its design philosophy emphasizes code readability and a syntax that allows programmers to express concepts in fewer lines of code than languages like C++ or Java.
In the following years, Python's popularity grew, and new versions were released, introducing new features and improving existing ones. Python 2.0, released in 2000, introduced support for Unicode and new features such as list comprehensions and generators. Python 3.0, released in 2008, introduced a number of backwards-incompatible changes aimed at improving the language's overall design and making it more consistent.
Today, Python is one of the most popular programming languages in the world, and it is widely used in many different fields, such as web development, data science, artificial intelligence, and more. Its popularity is due to its simple and easy-to-learn syntax, powerful standard library, and vast ecosystem of third-party libraries and frameworks.
Setting up a development environment
Please refer to this chapter to setup Python
Basic data types
Python has several built-in data types that are used to store and manipulate different types of data. These data types are:
Numbers:
Python has three built-in numeric types:
- integers (int),
- floating-point numbers (float), and
- complex numbers (complex). An integer is a whole number, a float is a number with a decimal point, and a complex numbers have a real and imaginary part.
# Numbers
x = 5 # integer
y = 3.14 # float
z = 2+3j # complex number
Strings:
A string is a sequence of characters enclosed in single or double quotes. Strings in Python are immutable, meaning that once created, their value cannot be changed.
# Strings
name = "John Doe"
Lists:
A list is an ordered collection of items. The items in a list can be of any data type, and they are enclosed in square brackets and separated by commas. Lists are mutable, meaning that their values can be changed.
# Lists
colors = ["red", "green", "blue"]
Tuples:
A tuple is similar to a list, but its elements are enclosed in parentheses and they are immutable.
# Tuples
coordinates = (2, 3)
Dictionaries:
A dictionary is an unordered collection of key-value pairs, where each key is unique. The keys and values are enclosed in curly braces and separated by colons. Dictionaries are mutable.
# Dictionaries
person = {"name": "John", "age": 30, "gender": "male"}
Boolean:
A boolean is a data type that can have one of two values, True or False. They are useful for controlling flow of the program and comparing values.
# Boolean
is_student = True
Variables and control structures
Variables
In Python, a variable is a named location in memory used to store a value. To create a variable, you simply give it a name and assign a value to it using the assignment operator (=)
. The value of the variable can be changed later on.
For example:
x = 5
y = "Hello"
z = [1, 2, 3]
In the above example, three variables x
, y
, and z
are created and assigned values of 5
, "Hello"
, and [1, 2, 3]
respectively.
Python has some naming conventions for variables, such as:
- Variable names can only contain letters, numbers, and underscores.
- They cannot start with a number.
- Variable names should be descriptive and cannot be the same as a Python keyword (e.g.
if
,for
,while
, etc.).
Control Structures
Control structures are used to control the flow of execution of a program. Python provides several control structures, such as:
If-else statements:
These are used to make decisions based on a certain condition. The syntax for an if-else statement is:
if condition:
# code to be executed if condition is True
else:
# code to be executed if condition is False
For example:
x = 5
if x > 0:
print("x is positive")
else:
print("x is negative")
For loops:
These are used to iterate over a sequence (such as a list or a tuple) and execute a block of code for each element. The syntax for a for loop is:
for variable in sequence:
# code to be executed for each element
For example:
colors = ["red", "green", "blue"]
for color in colors:
print(color)
While loops:
These are used to repeatedly execute a block of code while a certain condition is True. The syntax for a while loop is:
while condition:
# code to be executed
For example:
x = 5
while x > 0:
print(x)
x -= 1
It's important to note that indentation is important in Python, as it defines the scope of the control structures and loops. The code inside the control structures and loops should be indented by 4 spaces or one tab, and this indentation should be consistent throughout the program.
Functions and modules
Functions in Python:
Functions are a way to organize and reuse code.
A function is a block of code that can be called by other parts of the program and can accept input
(parameters
) and return output
(return value
).
In Python, you can define a function using the def
keyword, followed by the function name, a set of parentheses (which can contain parameters), and a colon. The code inside the function should be indented.
For example:
def greet(name):
"""This function greets the person passed in as a parameter"""
print("Hello, " + name + ". How are you today?")
greet("John")
In this example, the function greet()
takes in one parameter, name
, and prints out a greeting message. The function is called by passing in a value for the parameter, in this case "John"
.
Functions can also return a value using the return
keyword. For example:
def add(a, b):
"""This function adds two numbers and returns the result"""
return a + b
result = add(3, 4)
print(result)
In this example, the function add()
takes in two parameters, a
and b
, and returns their sum
. The returned value is then assigned to the variable result
and printed out.
Function Arguments:
Functions can take different types of arguments, such as positional arguments, keyword arguments, and default arguments.
Positional arguments:
These are passed to the function in the same order as they are defined in the function's signature. For example:
def add(a, b):
return a + b
result = add(3, 4)
print(result) # Output: 7
Keyword arguments:
These are passed to the function by specifying the argument name and its value. For example:
def greet(name, age):
print("Hello, " + name + ". You are " + str(age) + " years old.")
greet(name="John", age=30)
Default arguments:
These are arguments that have a default value defined in the function's signature, so they don't have to be passed to the function if not specified. For example:
def greet(name, age=18):
print("Hello, " + name + ". You are " + str(age) + " years old.")
greet("John") # Output: Hello, John. You are 18 years old.
Variable Scope
Variables defined in a function are only accessible within that function and are called local variables. Variables defined outside of a function are called global variables and can be accessed from anywhere in the program. It's important to be aware of variable scope to avoid naming conflicts and unexpected behavior.
File handling
File handling in Python allows you to read, write, and manipulate files on your computer. Here are some basic concepts and examples of file handling in Python:
Opening a file
To open a file in Python, you can use the built-in open()
function. The function takes in two arguments: the file path and the mode in which the file should be opened. The most common modes are 'r'
for reading, 'w'
for writing, and 'a'
for appending. For example:
file = open('example.txt', 'r')
Reading a file
Once a file is opened, you can read its contents using the read()
method. The method takes in an optional argument, specifying the number of bytes to read. If no argument is passed, it will read the entire file. For example:
file = open('example.txt', 'r')
contents = file.read()
print(contents)
file.close()
Writing to a file
To write to a file, you can use the write()
method. The method takes in a string as its argument and writes it to the file. If the file does not exist, it will be created. If the file already exists and you open it in write mode, its contents will be truncated (erased). For example:
file = open('example.txt', 'w')
file.write('This is a new line.')
file.close()
Appending to a file
To add new content to a file without erasing its existing contents, you can open the file in append mode ('a'
). The write()
method will then add the new content at the end of the file. For example:
file = open('example.txt', 'a')
file.write('This is an additional line.')
file.close()
Iterating over a file
Instead of reading the entire file at once, you can iterate over it line by line using a for
loop. The readlines()
method returns a list of all the lines in the file. For example:
file = open('example.txt', 'r')
for line in file:
print(line)
file.close()
Closing a file
Once you are done working with a file, it is important to close it using the close()
method to free up system resources.
with statement
If you open a file using the open()
function, you should close it after you are done working with it, to free up system resources. To ensure that a file is closed, even if an exception is raised, you can use the with
statement. The with
statement creates a context in which the file will be used, and it will automatically close the file when the block of indented code is finished. For example:
with open('example.txt', 'r') as file:
contents = file.read()
print(contents)
File handling is an important concept in Python and it allows you to work with files on your computer. These are just some basic examples of file handling in Python and there are more advanced concepts and methods available as well.
Exception handling
Exception handling is a mechanism in Python that allows you to handle and respond to errors that occur during the execution of your program. Here are some basic concepts and examples of exception handling in Python:
try-except statement
The most common way to handle exceptions in Python is by using the try-except
statement. The try
block contains the code that may raise an exception, and the except
block contains the code that will be executed if an exception is raised. For example:
try:
x = 5 / 0
except ZeroDivisionError:
print("You cannot divide by zero.")
In this example, the try
block raises a ZeroDivisionError
exception when trying to divide by zero, and the except
block catches the exception and prints a message.
Raising exceptions
You can also raise exceptions yourself using the raise
keyword. This is useful when you want to signal that an error has occurred and that the program should stop executing. For example:
def check_age(age):
if age < 18:
raise ValueError("You are not old enough.")
else:
print("Welcome!")
age = 15
try:
check_age(age)
except ValueError as error:
print(error)
In this example, the check_age()
function raises a ValueError
exception if the age is less than 18, and the try-except
block catches the exception and prints the error message.
The finally block
The finally
block contains code that will be executed no matter what, whether an exception was raised or not. This block is used to perform cleanup tasks, such as closing a file or a network connection. For example:
try:
file = open('example.txt', 'r')
contents = file.read()
print(contents)
except FileNotFoundError:
print("The file does not exist.")
finally:
file.close()
In this example, the try
block opens a file and reads its contents. If the file does not exist, the except block catches the FileNotFoundError
exception and prints an error message. The finally
block then closes the file, regardless of whether an exception was raised or not.
Object-oriented programming in Python
Object-oriented programming (OOP) is a programming paradigm that allows you to organize your code into reusable objects, each with its own properties and methods. Python is an object-oriented programming language, and understanding OOP concepts is essential for writing efficient and maintainable code in Python. Here are some basic concepts and examples of OOP in Python:
Classes
A class is a blueprint for creating objects (also called instances). It defines the properties and methods that the objects will have. For example:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
print("Woof woof!")
In this example, the Dog class has two properties, name
and age
, and one method, bark()
.
Objects/instances
An object, also called an instance, is a specific instance of a class. You can create an instance of a class by calling the class name as a function. For example:
dog1 = Dog("Fido", 3)
dog2 = Dog("Buddy", 5)
In this example, dog1
and dog2
are instances of the Dog class, with different values for the name
and age
properties.
Methods
Methods are functions that are defined inside a class, and they can access and manipulate the properties of the class. Methods are called on an instance of a class, using the dot
notation. For example:
dog1.bark() # Output: Woof woof!
In this example, the bark()
method is called on the dog1 instance, and it prints "Woof woof!"
Constructors
__init__()
function is a special method that is called when an object is created, it is known as constructor. This method can be used to initialize the properties of the class. For example:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
print("Woof woof!")
dog1 = Dog("Fido", 3)
In this example, the __init__
method is called when the dog1 object is created, and it sets the name and age properties of the object.
Inheritance
Inheritance allows you to create a new class that inherits properties and methods from an existing class. The new class, known as the derived class, inherits properties and methods from the existing class, known as the base class. This allows you to reuse code and create a hierarchy of classes. For example:
class GoldenRetriever(Dog):
def fetch(self):
print("Fetching...")
dog3 = GoldenRetriever("Max", 2)
dog3.bark() # Output: Woof woof!
dog3.fetch() # Output: Fetching...
In this example, the GoldenRetriever
class inherits from the Dog
class. dog3
is then instantiated with the name
and age
values.
Polymorphism
Polymorphism is the ability of a class to take on many forms, it allows classes to define methods that have the same name but with different implementations. For example:
class Animal:
def talk(self):
pass
class Dog(Animal):
def talk(self):
return "Woof woof!"
class Cat(Animal):
def talk(self):
return "Meow meow!"
dog = Dog()
cat = Cat()
print(dog.talk()) # Output: Woof woof!
print(cat.talk()) # Output: Meow meow!
In this example, the talk
method is defined in the base class Animal
and implemented in the derived classes Dog
and Cat
.
Encapsulation
Encapsulation is the process of hiding the internal state and behavior of an object from the outside world and providing a way to interact with the object through its public interface. In python, this can be achieved by using _
(underscore) before the property name. For example:
class BankAccount:
def __init__(self, balance=0):
self._balance = balance
Here, the _balance
property is considered as a private property, and we cannot access it directly from the outside.
Abstract classes
An abstract class is a class that cannot be instantiated, and it is used to provide a common interface for derived classes to implement. In python, we can use the abc
module to define abstract classes. For example:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side * self.side
sq = Square(5)
print(sq.area()) # Output: 25
Here, the Shape
class is an abstract class and it has an abstract method area that needs to be implemented by the derived classes.
These are some of the basic concepts of OOP in Python, and understanding these concepts is essential for writing efficient and maintainable code in Python.
Regular expressions
Regular expressions, also known as regex, are a powerful tool for manipulating strings in a concise and flexible way. Here is a beginner's tutorial on regular expressions in Python:
- Import the re module: To use regular expressions in Python, you need to first import the re module.
import re
- Create a pattern: A regular expression pattern is a specific string that describes a set of strings. You can create a pattern using a combination of special characters and normal characters. For example:
pattern = r"abc" # this pattern matches the string "abc"
- Use the
search()
function: Thesearch()
function searches for the first occurrence of a pattern in a string. It returns a match object if the pattern is found, orNone
if the pattern is not found. For example:
text = "abcdefg"
match = re.search(pattern, text)
print(match) # Output: <re.Match object; span=(0, 3), match='abc'>
- Use the
findall()
function: Thefindall()
function returns a list of all non-overlapping matches of a pattern in a string. For example:
text = "abcabcabc"
matches = re.findall(pattern, text)
print(matches) # Output: ['abc', 'abc', 'abc']
- Use the
sub()
function: Thesub()
function replaces all occurrences of a pattern in a string with a replacement string. For example:
text = "abcabcabc"
new_text = re.sub(pattern, "xyz", text)
print(new_text) # Output: 'xyzxyzxyz'
- Special characters:
.
Matches any character^
Matches the start of a string$
Matches the end of a string*
Matches 0 or more occurrences of the preceding character or group+
Matches 1 or more occurrences of the preceding character or group?
Matches 0 or 1 occurrence of the preceding character or group{m,n}
Matches from m to n occurrences of the preceding character or group[]
Matches any character within the brackets|
Matches either the expression before or the expression after the |()
Groups the enclosed characters\
Escapes special characters
- Compile the pattern: Compiling the pattern makes the execution faster.
pattern = re.compile(r"abc")
These are some of the basic concepts and functions of regular expressions in Python. With these tools, you can perform complex string manipulation tasks with just a few lines of code.
Debugging and testing
Debugging and testing are important aspects of software development, and Python provides several tools to help you with these tasks. Here is a beginner's tutorial on debugging and testing in Python:
Using print()
statements
One of the simplest ways to debug your code is to use print() statements to check the values of variables and expressions at various points in your code. For example:
def add(a, b):
c = a + b
print(c)
return c
print(add(2, 3)) # Output: 5
Using the pdb
module:
The pdb
module is a built-in Python library that provides a powerful command-line debugger. You can use pdb
to step through your code, set breakpoints, and inspect variables and expressions. To use pdb
, you can insert the following line of code in the place where you want to start debugging:
import pdb
def my_function():
# some code here
a = [1,2,3]
b = [4,5,6]
c = a + b
pdb.set_trace()
return c
my_function()
In this example, we are first importing the pdb
module. Then, we define a function my_function()
which contains some code and a call to pdb.set_trace()
. This call will start the interactive pdb debugger at that line, allowing you to step through the code, inspect variables, and more.
Unit testing
Unit testing is a technique that allows you to test individual units of your code to ensure they are working correctly. Python provides the unittest
module, which is a built-in library for unit testing. For example:
import unittest
def add(a, b):
return a + b
class TestAdd(unittest.TestCase):
def test_add_two_positive_numbers(self):
result = add(2, 3)
self.assertEqual(result, 5)
def test_add_two_negative_numbers(self):
result = add(-2, -3)
self.assertEqual(result, -5)
if __name__ == '__main__':
unittest.main()
Test-driven development
Test-driven development (TDD) is a software development approach in which tests are written before the implementation of the code. This approach helps you to write better code, as you are thinking about the test cases before writing the code.
Profiling
Profiling is a technique that allows you to measure the performance of your code. Python provides the cProfile
module, which is a built-in library for profiling Python code.
import cProfile
import pdb
def my_function():
# some code here
a = [1,2,3]
b = [4,5,6]
c = a + b
pdb.set_trace()
return c
cProfile.run('my_function()')
In this example, we are first importing the cProfile
and pdb
modules. Then, we define a function my_function()
which contains some code and a call to pdb.set_trace()
. This call will start the interactive pdb debugger at that line, allowing you to step through the code, inspect variables, and more.
After the function is defined, we use cProfile.run()
to run the function and profile it. cProfile.run()
will provide detailed information about the performance of the function, including the number of times each line of code was executed, the total time spent in each function, and more.
By combining the cProfile
and pdb
modules, you can gain a deeper understanding of your code's performance and behavior, and quickly identify and fix any issues.
Advanced topics
Decorators
Decorators are a powerful feature in Python that allow you to modify the behavior of functions and classes.
Defining a decorator
A decorator is a function that takes another function as an argument and returns a new function that modifies the behavior of the original function. For example:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before the function call")
result = func(*args, **kwargs)
print("After the function call")
return result
return wrapper
Applying a decorator
To apply a decorator to a function, you need to use the @
symbol followed by the decorator name before the function definition. For example:
@my_decorator
def my_function():
print("Hello, World!")
my_function()
# Output: Before the function call
# Hello, World!
# After the function call
Class-based decorators
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Before the function call")
result = self.func(*args, **kwargs)
print("After the function call")
return result
@MyDecorator
def my_function():
print("Hello, World!")
my_function()
# Output: Before the function call
# Hello, World!
# After the function call
Chaining decorators
You can chain multiple decorators together to modify the behavior of a function in multiple ways. For example:
def my_decorator1(func):
def wrapper(*args, **kwargs):
print("Decorator 1")
return func(*args, **kwargs)
return wrapper
def my_decorator2(func):
def wrapper(*args, **kwargs):
print("Decorator 2")
return func(*args, **kwargs)
return wrapper
@my_decorator1
@my_decorator2
def my_function():
print("Hello, World!")
my_function()
# Output: Decorator 1
# Decorator 2
# Hello, World!
Decorators can be a powerful tool for writing clean, modular, and reusable code, and they are widely used in Python.
Generators
Generators are a powerful feature in Python that allow you to create iterators in a more memory-efficient way.
Creating a generator
A generator is a special type of function that uses the yield
keyword to return a value and save the state of the function, so it can be resumed later. For example:
def my_generator():
yield 1
yield 2
yield 3
Using a generator
To use a generator, you need to call the generator function and assign it to a variable. The generator function returns a generator object, which can be used in a for
loop or with the next()
function. For example:
gen = my_generator()
for i in gen:
print(i)
# Output: 1
# 2
# 3
Generator expressions
Generator expressions are similar to list comprehensions, but they return a generator object instead of a list. They are denoted by enclosing the expression inside ()
instead of []
. For example:
gen = (i for i in range(10))
for i in gen:
print(i)
# Output: 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
Infinite Generators
def infinite_generator():
i = 0
while True:
yield i
i += 1
gen = infinite_generator()
print(next(gen)) # Output: 0
print(next(gen)) # Output: 1
print(next(gen)) # Output: 2
Closing a generator
Generators can be closed using the close() method, which raises a GeneratorExit
exception inside the generator function. Once closed, the generator cannot be resumed. For example:
gen = my_generator()
next(gen) # Output: 1
gen.close()
next(gen) # raises GeneratorExit
Practical Example
Here is a practical example of using generators and the yield keyword to read a large CSV file and process the data line by line:
name,age,gender,city
John Smith,35,male,New York
Emily Johnson,28,female,Chicago
Michael Brown,42,male,Los Angeles
Jessica Davis,31,female,Houston
This CSV file contains four columns: name, age, gender, and city, and four rows of data. Each row represents a person, and the columns represent their name, age, gender, and city. The first row of the file is the header row, which contains the names of the columns.
import csv
def process_csv(file_path):
with open(file_path, 'r') as file:
reader = csv.reader(file)
# Skip the header row
next(reader)
for row in reader:
yield row
def process_data(file_path):
for row in process_csv(file_path):
print("Processing: ", row)
# Do some processing on the row
# ...
process_data('large_data.csv')
In this example, we have a function process_csv(file_path)
that takes a file path as an argument and uses the open()
function to open the file. The csv.reader()
function is used to read the file line by line. The yield
keyword is used to return each row of the CSV file one at a time, instead of reading the entire file into memory at once.
The process_data()
function takes the file path and calls the process_csv()
function, which is a generator function. The function uses the for loop to iterate through the rows of the CSV file and calls the print()
function to print the current row. The function can then do any processing on the row before going to the next.
This approach of using generators and the yield
keyword is especially useful when working with large datasets that cannot fit into memory all at once, as it allows you to process the data incrementally, line by line, without having to load the entire dataset into memory.
By understanding and utilizing generators, you can improve the performance of your code and make it more memory-efficient, especially when working with large datasets.
Lambda functions
Lambda functions are a powerful feature in Python that allow you to create small, anonymous functions that can be passed as arguments to other functions.
Creating a lambda function
A lambda function is defined using the lambda keyword, followed by one or more arguments, a colon, and an expression that is returned by the function. For example:
add = lambda x, y: x + y
This lambda function takes two arguments, x
and y
, and returns their sum.
Using a lambda function
Once a lambda function is defined, you can use it just like a regular function. For example:
result = add(1, 2)
print(result) # Output: 3
Anonymous functions
Lambda functions are anonymous functions, meaning they do not have a name and cannot be referenced later in the code. They are used mostly to pass a small function as a parameter to another function.
Pass lambda function as an argument
numbers = [1, 2, 3, 4, 5]
result = list(filter(lambda x: x % 2 == 0, numbers))
print(result) # Output: [2, 4]
Comparison between lambda and regular function
add = lambda x, y: x + y
def add(x, y):
return x + y
Both examples are equivalent and can be used the same way.
Limitations
Lambda functions have some limitations:
- They can only contain a single expression, which means they can only perform a single operation.
- They cannot use statements, like if or for.
- They cannot contain docstrings or annotations.
Lambda functions are a useful tool for writing concise and readable code. They are often used in functional programming, and are particularly useful when working with higher-order functions like map()
, filter()
, and reduce()
.
Higher Order Functions
Higher-order functions are functions that take other functions as arguments or return them as output.
map()
function
The map()
function applies a given function to all items of an iterable (e.g. list, tuple, etc.) and returns an iterator. For example:
numbers = [1, 2, 3, 4, 5]
result = map(lambda x: x**2, numbers)
print(list(result)) # Output: [1, 4, 9, 16, 25]
filter()
function
The filter()
function filters the elements of an iterable based on a given function and returns an iterator. For example:
numbers = [1, 2, 3, 4, 5]
result = filter(lambda x: x % 2 == 0, numbers)
print(list(result)) # Output: [2, 4]
reduce()
function
The reduce()
function applies a given function cumulatively to the elements of an iterable and returns a single value. For example:
from functools import reduce
numbers = [1, 2, 3, 4, 5]
result = reduce(lambda x, y: x * y, numbers)
print(result) # Output: 120
zip()
function
The zip()
function takes two or more iterables and returns an iterator of tuples, where the i-th tuple contains the i-th element from each of the input iterables. For example:
a = [1, 2, 3]
b = [4, 5, 6]
result = zip(a, b)
print(list(result)) # Output: [(1, 4), (2, 5), (3, 6)]
sorted()
function
The sorted()
function returns a new sorted list from the items in an iterable. For example:
numbers = [3, 1, 4, 2, 5]
result = sorted(numbers)
print(result) # Output: [1, 2, 3, 4, 5]
By understanding and utilizing higher-order functions, you can write more expressive and readable code. These functions are very useful for functional programming, and are particularly useful when working with data processing and data manipulation tasks.
PEP8 Guidelines
PEP 8 is a set of guidelines for writing Python code, created by the Python community. It covers topics such as naming conventions, code layout, and documentation. Here are some of the key guidelines from PEP 8:
Indentation: Use 4 spaces per indentation level. Never mix tabs and spaces.
Line Length: Limit all lines to a maximum of 79 characters.
Imports: Imports should be grouped in the following order: standard library imports, third-party library imports, and local application/library specific imports.
# Standard library imports
import os
import sys
# Third-party library imports
import requests
from django.db import models
# Local application/library specific imports
from myproject.models import MyModel
from myproject.utils import my_function
- Naming Conventions:
- Functions and variable names should be lowercase, with words separated by underscores.
- Class names should be in CamelCase.
- Constants should be in UPPERCASE, with words separated by underscores.
White Space: Surround binary operators with a single space on either side.
Comments: Use inline comments sparingly, and use them to explain why the code is doing something, not what it is doing.
Docstrings: Use triple-quoted strings to write documentation for functions and classes.
Use of blank lines: Use blank lines to separate functions and classes, and to indicate logical sections within a function.
String Quotes: Use single quotes for strings unless the string contains a single quote.
Parentheses: Never use parentheses in expressions where they are not strictly necessary.
By following PEP 8 guidelines, your code will be more consistent and easier to read, making it simpler to maintain and collaborate with others. The guidelines are not strict rules, and you should adapt them to the project, team, and personal preference when needed.
Congratulations
Congrats on finishing the Python basics. This is far from a comprehensive Python course. But it will give you grasp of the basics and you can always refer to this refresher course to remember the basics of Python. Alright let us test your skills with an assessment.