Fundamentals 16 min read

Python Essentials: Strings, Collections, Iterators, and Decorators

This article presents a comprehensive collection of Python fundamentals, covering useful string methods like partition and translate, mutable versus immutable types and argument passing, tuple unpacking, dictionary utilities, set operations, iterator implementations, best practices for exception handling, and various decorator techniques with practical code examples.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Python Essentials: Strings, Collections, Iterators, and Decorators

The author, seeking to improve Python project structure, read the book "Python Craftsman" and extracted a series of useful snippets covering many core language features.

Uncommon but handy string methods : the partition method splits a string into three parts (before, separator, after) and can replace a multi‑line split implementation with a single line. Example:

<code>def extract_value(s):
    return s.partition(':')[2]</code>

The translate method performs bulk character replacement efficiently:

<code>s = "Hello, World!"
table = str.maketrans(",!", ".~")
print(s.translate(table))  # Hello. World~</code>

Long multi‑line strings can have their indentation cleaned using textwrap.dedent :

<code>from textwrap import dedent

def welcome():
    return dedent("""Welcome to my website.
        - I'm a Python developer.
        - I love coding.
    """)</code>

Defining enumerations with the built‑in enum module:

<code>from enum import Enum
class Color(int, Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

color = Color.RED
print(1 == color)  # True</code>

Mutable vs. immutable types and function argument passing : Python passes arguments by object reference. Modifying an immutable argument creates a new object, while modifying a mutable argument alters the original. Illustrations:

<code>def add_string(s):
    s += 'world'
    return s

s = 'hello'
print(add_string(s))  # helloworld
print(s)               # hello

def add_list(l):
    l.append('world')
    return l

l = ['hello']
print(add_list(l))  # ['hello', 'world']
print(l)            # ['hello', 'world']</code>

Functions can return multiple values as a tuple, which can be unpacked:

<code>def get_name_and_age():
    return 'John', 30

result = get_name_and_age()
print(type(result))  # <class 'tuple'>
</code>

Named tuples improve readability:

<code>from collections import namedtuple
Rectangle = namedtuple('Rectangle', ['width', 'height'])
rect = Rectangle(10, 20)
print(rect.width, rect.height)
</code>

Dictionary utilities : get provides a default for missing keys, setdefault inserts a value when the key is absent, and pop can return a default instead of raising KeyError :

<code>d = {}
# using setdefault
d.setdefault('item', []).append('new_value')
</code>

Set operations such as difference, union, and intersection are demonstrated:

<code>s1 = {1, 2, 3, 4}
s2 = {3, 4, 5, 6}
print(s1 - s2)  # {1, 2}
print(s1 | s2)  # {1, 2, 3, 4, 5, 6}
print(s1 &amp; s2)  # {3, 4}
</code>

Merging dictionaries can be done with unpacking or the | operator:

<code>d1 = {'a': 1, 'b': 2}
d2 = {'c': 3, 'd': 4}
d3 = {**d1, **d2}
d4 = d1 | d2
</code>

Exception handling best practices : place more specific except clauses before generic ones, use try...else to separate successful execution logic, and avoid catching overly broad exceptions.

<code>def incr_by_key(d, key):
    try:
        d[key] += 1
    except KeyError as e:
        print(e)
</code>

Iterables and iterators : an iterator implements both __iter__ and __next__ . A simple range‑like iterator can be written as:

<code>class MyRange:
    def __init__(self, start, end):
        self.start = start
        self.end = end
        self.current = start
    def __iter__(self):
        return self
    def __next__(self):
        if self.current < self.end:
            cur = self.current
            self.current += 1
            return cur
        raise StopIteration
</code>

To make the object reusable, separate the iterable from the iterator:

<code>class MyRange:
    def __init__(self, start, end):
        self.start = start
        self.end = end
    def __iter__(self):
        return MyRangeIterator(self)

class MyRangeIterator:
    def __init__(self, my_range):
        self.my_range = my_range
        self.current = my_range.start
    def __next__(self):
        if self.current < self.my_range.end:
            cur = self.current
            self.current += 1
            return cur
        raise StopIteration
    def __iter__(self):
        return self
</code>

A generator using yield provides an even shorter implementation:

<code>def my_range(start, end):
    while start < end:
        yield start
        start += 1
</code>

Function default mutable arguments are a common pitfall; using a mutable default leads to shared state across calls:

<code>def f(a, L=[]):
    L.append(a)
    return L

print(f(1))  # [1]
print(f(2))  # [1, 2]
</code>

Keyword‑only arguments are enforced by placing a * in the signature:

<code>def f(a, *, b):
    print(a, b)

f(1, b=2)
</code>

Decorators : using functools.wraps preserves the original function’s metadata. An example timing decorator:

<code>def time_it(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        ret = func(*args, **kwargs)
        end = time.time()
        print(f'{func.__name__} took {end - start} seconds')
        return ret
    return wrapper
</code>

Optional parameters can be added by returning a decorator factory, and a class can be made callable to act as a decorator:

<code>class Timer:
    def __init__(self, unit='s'):
        self.unit = unit
    def __call__(self, func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time.time()
            ret = func(*args, **kwargs)
            end = time.time()
            if self.unit == 's':
                print(f'{func.__name__} took {end - start} seconds')
            else:
                print(f'{func.__name__} took {(end - start) * 1000} ms')
            return ret
        return wrapper
</code>

The article concludes with a promotional QR code for a free Python public course, but the technical content above provides a solid reference for Python developers.

PythonIteratorsCollectionsdecoratorsstrings
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.