An In-Depth Guide to Python Data Types

Python provides a rich set of built-in data types that enable you to work with different kinds of data in your programs.

The core numeric types are integers, floats, and complex numbers. Integers represent whole numbers, which are useful for exact counts and computations.

Floats represent real numbers with decimal precision, which is important for scientific and statistical calculations. Complex numbers extend numbers to the complex plane and are used in many scientific domains.

Python has many built-in data types that enable you to store and manipulate data in powerful ways. Choosing the appropriate data type for your use case is important for writing optimized Python code.

This comprehensive guide will explore the various Python data types with code examples.

Numeric Types

Numeric data types in Python allow you to work with numeric data like integers, floats, and complex numbers. Let's look at each of the numeric types in detail:

Integer (int)

Integers are whole numbers like -2, -1, 0, 1, 2, 3 etc. They can be positive, negative or 0. Integers are immutable in Python. Some examples:

x = 10    # positive integer
y = -5    # negative integer 
print(type(x)) # <class 'int'>

We can perform mathematical operations on integers like addition, subtraction, multiplication etc.

a = 12
b = 4
print(a + b) # 16 

print(a - b) # 8

print(a * b) # 48

Integers can be converted to other data types like float, complex etc.

num = 10

print(type(num)) # <class 'int'> 


num2 = float(num)

print(type(num2)) # <class 'float'>

Floating-Point (float)

Floats represent real numbers like -1.5, -0.4, 0.0, 1.25, 9.8 etc. They contain a decimal point. Useful for computations where precision is required. Some examples:

a = 1.5   

b = -0.4

print(type(a)) # <class 'float'>

Floats support math operations like addition, subtraction etc.

x = 3.0

y = 5.5 


print(x + y) # 8.5

print(x - y) # -2.5 

print(x * y) # 16.5

They can be converted to other types like int, complex etc.

a = 1.2

print(type(a)) # <class 'float'>


b = int(a) 

print(type(b)) # <class 'int'>

Complex

Complex numbers are written as x + yj, where x is the real part, and y is the imaginary part. They are useful for scientific and mathematical applications.

x = 5 + 3j


print(type(x)) # <class 'complex'>

We can perform operations like addition and multiplication on complex numbers.

a = 2+3j

b = 5+4j


print(a + b) # 7+7j 

print(a * b) # -7+26j

They can be converted to other types like int, float etc.

x = 5 + 3j
print(type(x)) # <class 'complex'>

y = float(x)
print(type(y)) # <class 'float'>

Boolean Type

Boolean represents logical values True and False. Useful for conditional testing and logic. For example:

x = True
y = False
print(type(x)) # <class 'bool'>

Boolean operators like and, or, not can be used to compose logical expressions and conditions.

a = True
b = False
print(a and b) # False 
print(a or b) # True
print(not a) # False

Other data types can be converted to booleans based on their truth value.

x = 5
print(bool(x)) # True 
y = 0
print(bool(y)) # False

Sequence Types

Sequence types allow storing collections of data in an ordered way. Let's go through them one by one:

String (str)

Strings represent sequences of unicode characters like letters, digits, spaces etc. They are immutable in Python. Some examples of creating strings:

s1 = 'Hello'
s2 = "World"
print(type(s1)) # <class 'str'>

We can access individual characters using indexing:

s = 'python'
print(s[0]) # p
print(s[3]) # h

Strings support operations like concatenation, slicing, length etc.

s1 = 'Hello'
s2 = 'World'
print(s1 + ' ' + s2) # Hello World
print(len(s1)) # 5

Format specifiers like %s can be used for formatting:

name = 'John'
print('My name is %s' % name) # My name is John

List

Lists are ordered collections of values that are mutable (modifiable). Allows for storing different data types.

nums = [1, 2, 3] 
fruits = ['apple', 'mango', 'banana']
print(type(nums)) # <class 'list'>

We can access elements using index. Lists are mutable.

nums[0] = 5 
print(nums) # [5, 2, 3]

Lists support operations like concatenation, slicing, length etc.

fruits = ['apple', 'banana', 'mango']
print(len(fruits)) # 3
print(fruits[1:]) # ['banana', 'mango']

Tuple

Tuples are ordered collections of values that are immutable (cannot be modified). Allows storing different data types.

point = (2, 3) # parenthesis not required but recommended
colors = ('red', 'blue', 'green')
print(type(point)) # <class 'tuple'>

We can access elements using an index but cannot modify tuples.

point[0] = 5 #ERROR: cannot modify tuple

Tuples support operations like concatenation, slicing, length etc.

colors = ('red', 'blue', 'green')  
print(len(colors)) # 3
print(colors[1:]) # ('blue', 'green')

Range

A range represents an immutable sequence of numbers. It is commonly used to loop over sequences of numbers.

nums = range(5) # 0 to 4 
print(list(nums)) # [0, 1, 2, 3, 4]

Ranges are often used in for loops:

for i in range(3):
   print(i)
# Output:
# 0
# 1  
# 2

We can also create ranges with a start, stop, and step size.

nums = range(3, 8, 2) 
print(list(nums)) # [3, 5, 7]

Set Types

Sets are unordered collections of unique values. They support operations like membership testing, set math etc.

Set

Sets contain unique values only. Elements can be added and removed.

colors = {'red', 'blue', 'green'}
print(type(colors)) # <class 'set'>

Set elements can be tested for membership and added/removed. Sets are mutable.

'red' in colors # True
colors.add('yellow')
colors.remove('blue')

Set math operations like union intersection work between sets.

set1 = {1, 2, 3}
set2 = {3, 4, 5}
print(set1 | set2) # {1, 2, 3, 4, 5}
print(set1 & set2) # {3}

Frozenset

Frozenset is an immutable variant of a Python set. Elements cannot be added or removed.

colors = frozenset(['red', 'blue', 'green'])
print(type(colors)) # <class 'frozenset'> 
colors.add('yellow') # AttributeError

frozensets can be used as dictionary keys and in set operations.

Mapping Type

Mapping types allow storing data as key-value pairs. Dictionaries are the main mapping type in Python.

Dictionary

Dictionaries consist of key-value pairs and are enclosed in curly braces {}. Useful for storing related data.

student = {
  'name': 'John',
  'age': 20, 
  'courses': ['Math', 'Science']
}
print(type(student)) # <class 'dict'>

Dictionary elements can be accessed via keys and modified. Dictionaries are mutable.

student['name'] = 'Mark' # update value
print(student['courses']) # ['Math', 'Science']

Common dict operations include length, adding/removing keys, iteration etc.

print(len(student)) # 3 
student['email'] = 'john@example.com' # add key-value
for key in student:
    print(key, student[key]) # print each item

Binary Types

Binary types in Python are used when working with binary data like bytes, byte arrays, etc.

Bytes

Bytes represent immutable sequences of bytes. Example:

data = b'hello' 
print(type(data)) # <class 'bytes'>

Bytes support operations like indexing, length, concatenation, etc., but are immutable.

print(data[0]) # 104
print(len(data)) # 5
data2 = data + b'world' # cannot modify, only concatenate

Bytearray

Bytearray represents mutable sequences of bytes. They can be modified in place.

data = bytearray(b'hello')
print(type(data)) # <class 'bytearray'>  
data[0] = 106 # mutable

Bytearray supports typical sequence operations like indexing, concatenation etc.

print(data[0]) # 106 
data2 = data + bytearray(b'world')

Memoryview

Memoryview objects allow accessing the internal data of objects that support the buffer protocol directly without copying. Useful for advanced optimizations.

data = memoryview(b'hello')
print(data[0]) # 104

Memoryview supports slicing and editing without copying the buffer. Advanced usage for performance.

data[1:4] = b'i' # edit in place
print(data) # b'hiello'

None Type

The None type represents the absence of a value. It is similar to null in other languages.

x = None 
print(type(x)) # <class 'NoneType'>

None is commonly used as a placeholder for optional or missing values.

def print_if_not_none(x):
    if x is None:
        print('x is None')
    else:
        print(x)

The operator can check if something is None.

x = None
print(x is None) # True

So, in summary, Python comes equipped with a diverse set of built-in data types - numeric, textual, collections, mappings, and more.

Choosing the appropriate data type leads to efficient memory usage and better performance. Manipulating data types form an integral part of Python programming.

I hope this overview gave you a good understanding of the different data types available in Python, along with plenty of code examples demonstrating their usage.