Python Gotchas, C/C++ Migration Tips, and Handy Utilities
This article presents a collection of Python pitfalls such as random sampling, lambda binding, copying, equality vs identity, and type checks, followed by a concise guide for C/C++ programmers transitioning to Python, and showcases useful tools like CSV handling, itertools, collections, and performance‑debugging techniques.
1. Commonly Confusing Operations
This section compares several Python operations that are often confused.
1.1 Random sampling with and without replacement
import random
random.choices(seq, k=1) # list of length k, sampling with replacement
random.sample(seq, k) # list of length k, sampling without replacement1.2 Lambda function arguments
func = lambda y: x + y # x is bound at function execution time
func = lambda y, x=x: x + y # x is bound at function definition time1.3 copy vs deepcopy
import copy
y = copy.copy(x) # shallow copy, only top‑level objects are copied
y = copy.deepcopy(x) # deep copy, all nested objects are copiedWhen combined with variable aliases, copying can be confusing:
a = [1, 2, [3, 4]]
# Alias.
b_alias = a
assert b_alias == a and b_alias is a
# Shallow copy.
b_shallow_copy = a[:]
assert b_shallow_copy == a and b_shallow_copy is not a and b_shallow_copy[2] is a[2]
# Deep copy.
import copy
b_deep_copy = copy.deepcopy(a)
assert b_deep_copy == a and b_deep_copy is not a and b_deep_copy[2] is not a[2]Modifying an alias affects the original variable; shallow copies keep references to inner objects, while deep copies are fully independent.
1.4 == vs is
x == y # compare values
x is y # compare object identity1.5 Type checking
type(a) == int # ignores polymorphism
isinstance(a, int) # respects polymorphism1.6 String searching
str.find(sub, start=None, end=None) # returns -1 if not found
str.index(sub, start=None, end=None) # raises ValueError if not found1.7 List reverse indexing
Python allows reverse indexing; using the bitwise NOT operator (~) can start reverse indices at 0.
print(a[-1], a[-2], a[-3])
print(a[~0], a[~1], a[~2])2. Guide for C/C++ Users
Many Python users come from C/C++; this section highlights syntactic and idiomatic differences.
2.1 Very large and very small numbers
a = float('inf')
b = float('-inf')2.2 Boolean values
a = True
b = False2.3 Checking for emptiness
In C/C++ a null pointer is checked with if (a) or if (!a). In Python use:
if x is None:
passUsing if not x treats empty strings, lists, tuples, dicts, etc., as false.
2.4 Swapping values
C/C++ typically uses a temporary variable; Python can swap in one line: a, b = b, a 2.5 Comparisons
C/C++ often writes two separate conditions; Python supports chained comparisons:
if 0 < a < 5:
pass2.6 Class member getters and setters
While C/C++ encourages private members with explicit get/set functions, Python can use @property but should avoid unnecessary abstraction because it can be 4‑5× slower than direct access.
2.7 Function input/output parameters
C/C++ passes output parameters via pointers and returns a status code. Python raises exceptions directly for error handling.
2.8 File reading
Python simplifies file I/O; opened files are iterable line by line:
with open(file_path, 'rt', encoding='utf-8') as f:
for line in f:
print(line) # trailing '
' is retained2.9 Path concatenation
Instead of manual string concatenation, use os.path.join:
import os
os.path.join('usr', 'lib', 'local')2.10 Command‑line option parsing
Python’s argparse.ArgumentParser is more powerful than manually handling sys.argv.
2.11 Invoking external commands
Prefer subprocess.check_output over os.system for better control:
import subprocess
# Simple call, raises CalledProcessError on non‑zero exit
result = subprocess.check_output(['cmd', 'arg1', 'arg2']).decode('utf-8')
# Capture stderr as well
result = subprocess.check_output(['cmd', 'arg1', 'arg2'], stderr=subprocess.STDOUT).decode('utf-8')
# Run a shell pipeline
result = subprocess.check_output('grep python | wc > out', shell=True).decode('utf-8')2.12 Avoid reinventing the wheel
Python follows the “batteries‑included” philosophy, providing many ready‑made solutions.
3. Common Tools
3.1 Reading and writing CSV files
import csv
# No header
with open(name, 'rt', encoding='utf-8', newline='') as f:
for row in csv.reader(f):
print(row[0], row[1])
with open(name, mode='wt') as f:
f_csv = csv.writer(f)
f_csv.writerow(['symbol', 'change'])
# With header
with open(name, mode='rt', newline='') as f:
for row in csv.DictReader(f):
print(row['symbol'], row['change'])
with open(name, mode='wt') as f:
header = ['symbol', 'change']
f_csv = csv.DictWriter(f, header)
f_csv.writeheader()
f_csv.writerow({'symbol': xx, 'change': xx})For very large CSV files, increase the field size limit:
import sys
csv.field_size_limit(sys.maxsize)CSV can also read tab‑delimited data:
f = csv.reader(f, delimiter='\t')3.2 itertools utilities
import itertools
itertools.islice(iterable, start=None, stop, step=None)
itertools.filterfalse(predicate, iterable)
itertools.takewhile(predicate, iterable)
itertools.dropwhile(predicate, iterable)
itertools.compress(iterable, selectors)
sorted(iterable, key=None, reverse=False)
itertools.groupby(iterable, key=None)
itertools.permutations(iterable, r=None)
itertools.combinations(iterable, r=None)
itertools.combinations_with_replacement(...)
itertools.chain(*iterables)
import heapq
heapq.merge(*iterables, key=None, reverse=False)
zip(*iterables)
itertools.zip_longest(*iterables, fillvalue=None)3.3 Counter
import collections
counter = collections.Counter(iterable)
freq = collections.Counter[key]
most_common = collections.Counter.most_common(n=None)
counter.update(iterable)
counter1 + counter2
counter1 - counter2
collections.Counter(list1) == collections.Counter(list2)3.4 defaultdict with default values
import collections
d = collections.defaultdict(type) # type() called with no args for missing keys3.5 OrderedDict
import collections
od = collections.OrderedDict(items=None) # preserves insertion order during iteration4. High‑Performance Programming and Debugging
4.1 Writing errors and warnings
import sys
sys.stderr.write('error message') import warnings
warnings.warn(message, category=UserWarning)
# Categories: DeprecationWarning, SyntaxWarning, RuntimeWarning, ResourceWarning, FutureWarningControl warning output from the command line:
$ python -W all # show all warnings
$ python -W ignore # ignore all warnings
$ python -W error # turn warnings into exceptions4.2 In‑code testing (debug prints)
# Debug block
if __debug__:
print('debug info')Running Python with -O removes these blocks.
$ python -O main.py4.3 Code style checking
pylint main.py4.4 Measuring execution time
$ python -m cProfile main.pyTiming a specific block:
from contextlib import contextmanager
from time import perf_counter
@contextmanager
def timeblock(label):
tic = perf_counter()
try:
yield
finally:
toc = perf_counter()
print('%s : %s' % (label, toc - tic))
with timeblock('counting'):
passPerformance‑optimisation principles:
Focus on bottlenecks, not the whole code.
Avoid global variables; local look‑ups are faster.
Prefer local variable access over attribute access.
Use built‑in data structures (str, list, set, dict) implemented in C.
Avoid unnecessary intermediate variables and copy.deepcopy().
Prefer ':'.join([...]) over repeated string concatenation.
5. Other Python Tricks
5.1 argmin and argmax
items = [2, 1, 3, 4]
argmin = min(range(len(items)), key=items.__getitem__)
# argmax is analogous5.2 Transposing a 2‑D list
A = [['a11', 'a12'], ['a21', 'a22'], ['a31', 'a32']]
A_transpose = list(zip(*A)) # list of tuples
A_transpose = [list(col) for col in zip(*A)] # list of lists5.3 Converting a 1‑D list to a 2‑D list
A = [1, 2, 3, 4, 5, 6]
# Preferred method
list(zip(*[iter(A)] * 2))Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
