📌Free Shipping for all orders over $60. Just add merch to cart. Applied at checkout.

You know what’s worse than debugging? Debugging someone else’s ugly, overcomplicated code. Python is designed to be elegant and readable, yet somehow, bad coding habits still thrive.

Whether you’re writing scripts, APIs, or production-level applications, these 10 Python tricks will make your code cleaner, faster, and easier to maintain—while saving your future self (or your team) from unnecessary suffering.

Let’s go. 🚀

Python Programming Tips to be a better dev.

Table of contents

1. Swap Variables Without a Temporary Variable

You’re writing a function that processes two numbers but need to swap them before performing calculations. You’re tempted to do it the classic way with a temp variable.

Bad Code (Old-School Swap)

temp = a
a = b
b = temp

Why This Is Bad:

  • Uses an unnecessary extra variable.
  • More lines = more clutter.
  • Increases memory usage slightly (negligible, but still unnecessary).

Better Code (Pythonic Swap Using Tuple Unpacking)

a, b = b, a

When to Use This:

  • Anytime you swap two values, whether they’re numbers, strings, or objects.
  • Example: Swapping player scores in a game leaderboard.
score1, score2 = score2, score1

💡 When Should You NOT Use This?
If you’re swapping multiple values in a huge dataset, consider using an in-place swap inside a function to avoid unnecessary reallocation.

2. Use List Comprehensions for Cleaner Loops

You’re filtering and modifying a list, but your for loop is making the function longer than it should be.

Bad Code (Verbose Loop)

pythonCopyEditsquared = []
for num in range(10):
    squared.append(num ** 2)

Why This Is Bad:

  • Takes three lines instead of one.
  • append() calls in a loop slow things down.
  • Not immediately readable—you have to scan multiple lines to see what’s happening.

Better Code (List Comprehension)

pythonCopyEditsquared = [num ** 2 for num in range(10)]

When to Use This:

  • When performing simple transformations on lists.
  • Example: Generating a list of even numbers.
pythonCopyEditevens = [num for num in range(20) if num % 2 == 0]

💡 Aside: When to Stick with a for Loop?
If your loop involves complex logic (multiple conditions, nested structures), a list comprehension can hurt readability. Keep it simple.

3. Get Default Dictionary Values Without Errors

You’re fetching user data, but not every user has the same fields. You try to access user_data["age"] and boom—KeyError.

Bad Code (Using Try-Except for Missing Keys)

pythonCopyEdittry:
    age = user_data['age']
except KeyError:
    age = 25  # Default value

Why This Is Bad:

  • Overkill—exceptions should be used for actual errors, not predictable missing values.
  • Slower execution—handling exceptions takes time.

Better Code (.get() Method FTW)

pythonCopyEditage = user_data.get('age', 25)

When to Use This:

  • When fetching values from a dictionary that may not have all keys.
  • Example: Getting a user’s preferred theme (default to light mode).
pythonCopyEdittheme = settings.get('theme', 'light')

💡 When Should You Use try-except?
When you must raise an error if the key is missing—like missing API credentials or required fields in a config file.


4. Merge Dictionaries Without a Loop

You’re merging two sets of config settings, but you’re doing it the old-school way.

Bad Code (Manual Merge)

pythonCopyEditcombined = dict1.copy()
combined.update(dict2)

Why This Is Bad:

  • Unnecessary copying—wasteful if dealing with large dictionaries.
  • Multiple lines for a simple operation.

Better Code (Python 3.9+ | Operator)

pythonCopyEditcombined = dict1 | dict2

When to Use This:

  • When merging two dictionaries in Python 3.9+.
  • Example: Merging default and user-defined app settings.
pythonCopyEditconfig = default_settings | user_settings

💡 What If You’re Using Python < 3.9?
Use {**dict1, **dict2} instead—it’s still a one-liner.


5. Use Enumerate Instead of Manual Index Tracking

You’re looping through a list while tracking indices manually.

Bad Code (Manual Index Tracking)

pythonCopyEditindex = 0
for item in my_list:
    print(index, item)
    index += 1

Why This Is Bad:

  • Manually managing index is pointless overhead.
  • If you forget index += 1, your loop breaks.

Better Code (enumerate() FTW)

pythonCopyEditfor index, item in enumerate(my_list):
    print(index, item)

When to Use This:

  • When you need an index while iterating over a list.
  • Example: Labeling items in a leaderboard.
pythonCopyEditfor rank, player in enumerate(players, start=1):
    print(f"{rank}. {player}")

💡 When Not to Use enumerate()?
If you’re modifying the list while iterating—stick to for i in range(len(list)).


6. Use zip() for Clean Parallel Iteration

You’re working with two lists that need to be processed together—maybe names and ages, or product IDs and prices. Instead of looping manually with indices, there’s a better way.

Bad Code (Manual Indexing = Messy & Prone to Errors)

pythonCopyEditfor i in range(len(names)):
    print(f"{names[i]} is {ages[i]} years old.")

Why This Is Bad:

  • Manually handling indices makes the code harder to read.
  • If names and ages are different lengths, this throws an IndexError.
  • Less Pythonic—you’re writing C-style code in Python.

Better Code (Use zip())

pythonCopyEditfor name, age in zip(names, ages):
    print(f"{name} is {age} years old.")

When to Use This:

  • Anytime you’re pairing related items from multiple lists.
  • Example: Iterating over dictionary keys and values in one go.
pythonCopyEditfor key, value in my_dict.items():
    print(f"{key}: {value}")
  • Avoid it when: You need indexed access to individual elements inside the loop.

💡 What If Your Lists Are Different Lengths?
Use zip_longest() from itertools if you need to handle cases where lists aren’t the same size.

pythonCopyEditfrom itertools import zip_longest
for name, age in zip_longest(names, ages, fillvalue="Unknown"):
    print(f"{name} is {age} years old.")

7. Use .join() for Efficient String Concatenation

You’re building a large string by adding words together in a loop. Concatenation seems simple, but there’s a hidden performance cost if done incorrectly.

Bad Code (String Concatenation in a Loop = Slow AF)

pythonCopyEditsentence = ""
for word in words:
    sentence += word + " "

Why This Is Bad:

  • Strings are immutable in Python—every += operation creates a new string in memory, which is slow.
  • In large loops, this can cause performance issues.

Better Code (Use join() for Efficiency)

pythonCopyEditsentence = " ".join(words)

When to Use This:

  • Anytime you need to concatenate multiple strings efficiently.
  • Example: Formatting log messages.
pythonCopyEditlog_message = " | ".join([timestamp, log_level, message])
  • Avoid it when: You’re working with a small, fixed number of strings (e.g., "Hello " + name).

💡How Bad Is the Performance Hit?
In large-scale applications, improper string concatenation slows things down drastically. Benchmark results show .join() is 100x faster than manual concatenation in big loops.


8. Use sorted() Instead of Writing Your Own Sorting Logic

You’re working with a dictionary where values need to be sorted, and instead of using Python’s built-in tools, you write a manual sorting function (yikes).

Bad Code (Sorting the Hard Way = Unnecessary Complexity)

pythonCopyEditsorted_items = []
for key, value in my_dict.items():
    sorted_items.append((key, value))

sorted_items.sort(key=lambda item: item[1])

Why This Is Bad:

  • Unnecessary manual sorting—Python has built-in functions for this.
  • More lines than needed = more maintenance pain.

Better Code (Use sorted() for One-Liner Sorting)

pythonCopyEditsorted_items = sorted(my_dict.items(), key=lambda x: x[1])

When to Use This:

  • When sorting dictionaries, lists, or tuples by specific attributes.
  • Example: Sorting a list of user objects by age.
pythonCopyEditusers = sorted(user_list, key=lambda u: u.age)
  • Avoid it when: Sorting huge datasets—consider heapq.nsmallest() for efficiency.

Want Reverse Order?

Just add reverse=True.

pythonCopyEditsorted_items = sorted(my_dict.items(), key=lambda x: x[1], reverse=True)

9. Use defaultdict to Avoid KeyErrors and Manual Checks

You’re working with a dictionary where keys are dynamically added, but you find yourself writing manual checks every time.

Bad Code (Manually Checking for Keys)

pythonCopyEditword_counts = {}
for word in words:
    if word in word_counts:
        word_counts[word] += 1
    else:
        word_counts[word] = 1

Why This Is Bad:

  • Too much boilerplateif key in dict should not be necessary.
  • Can be replaced with a more Pythonic structure.

Better Code (Use defaultdict to Handle Missing Keys Automatically)

pythonCopyEditfrom collections import defaultdict

word_counts = defaultdict(int)
for word in words:
    word_counts[word] += 1

When to Use This:

  • Anytime you need default values in a dictionary.
  • Example: Categorizing items without predefining keys.
pythonCopyEditfrom collections import defaultdict
categories = defaultdict(list)
categories['fruits'].append('apple')

Counter Might Be Even Better

If you’re counting occurrences, consider using Counter instead.

pythonCopyEditfrom collections import Counter
word_counts = Counter(words)

10. Use Generators Instead of Creating Large Lists in Memory

You need to iterate over a massive dataset, but creating a full list in memory is inefficient.

Bad Code (Building a Huge List in Memory)

pythonCopyEditsquared_numbers = [num ** 2 for num in range(10_000_000)]

Why This Is Bad:

  • Consumes too much memory—the entire list is created before iteration.
  • Can cause memory overflow in large-scale applications.

Better Code (Use a Generator to Yield Values Lazily)

pythonCopyEditsquared_numbers = (num ** 2 for num in range(10_000_000))

When to Use This:

  • When dealing with large data processing that doesn’t need all values stored at once.
  • Example: Streaming large logs instead of storing them in memory.
pythonCopyEditdef read_large_file(file_path):
    with open(file_path) as f:
        for line in f:
            yield line.strip()
  • Avoid it when: You actually need a full list for indexing or random access.

Want a Full Generator Function?

Instead of a generator expression, you can use a full function with yield.

pythonCopyEditdef squared_numbers(limit):
    for num in range(limit):
        yield num ** 2

Final Thoughts: Write Pythonic Code or Suffer

Writing clean Python code is not just about being fancy—it makes your life easier when debugging, maintaining, and scaling projects.

Key Takeaways:
Use built-in methods (get(), zip(), enumerate()) to avoid manual work.
Leverage Python-specific features like tuple unpacking and list comprehensions.
Make your code readable—don’t just aim for brevity at the cost of clarity.

And remember, bad code compounds like tech debt—write better today, thank yourself later.

👕 Want to flex your Python skills IRL? Check out MadDosh’s Python-themed apparel and wear your coder mindset with pride. 🚀


Leave a Reply

Your email address will not be published. Required fields are marked *