如何将字符计数型字符串压缩代码优化为Python风格?
Hey there! Let's take your existing string compression logic and tweak it to fit Python's idiomatic style—cleaner, more efficient, and easier to read. First, here's your original code (I filled in the truncated return statement for context):
def string_contraction(input_string): if type(input_string) != str: print("Not a string") return input_string = str.lower(input_string) prev = input_string[0] s = "" i = 0 for lett in input_string: if lett == prev: i += 1 else: s += prev+str(i) prev = lett i = 1 s += lett+str(i) return s
Now let's break down the optimizations:
1. Better Type Checking & Error Handling
Instead of type(input_string) != str, use isinstance(input_string, str)—this is the standard Python way to check types, as it works correctly with inheritance (even though str has no built-in subclasses, it's a good habit to follow).
Also, printing an error message and returning silently isn't ideal. Instead, raise a TypeError—this lets the caller handle the error appropriately, which aligns with Python's "explicit is better than implicit" philosophy.
2. Correct String Lowercasing
Your code uses str.lower(input_string), but the proper way to call the lowercase method is input_string.lower(). Both work, but the latter is the standard instance method style Python developers expect.
3. Avoid Inefficient String Concatenation
Strings in Python are immutable, so every time you do s += ..., you're creating a new string. For long input strings, this gets slow fast. Instead, collect your compressed chunks in a list and join them at the end with ''.join()—this is much more efficient.
4. Use itertools.groupby for Clean Grouping
Python's itertools.groupby was made exactly for this kind of problem: grouping consecutive identical characters. It simplifies the code drastically by handling the grouping logic for you, so you just need to count the length of each group.
Revised, Pythonic Code
from itertools import groupby def string_compress(input_string): # Validate input type if not isinstance(input_string, str): raise TypeError("Input must be a string") # Handle empty string edge case (your original code would crash here!) if not input_string: return "" lower_input = input_string.lower() compressed_parts = [] # Group consecutive characters and build compressed string for char, consecutive_group in groupby(lower_input): compressed_parts.append(f"{char}{len(list(consecutive_group))}") return "".join(compressed_parts)
Bonus: Handle Edge Cases
I added a check for empty strings—your original code would throw an IndexError if given an empty input, which is a common edge case to cover.
Test It Out
Here's how the revised code works with your example and other cases:
print(string_compress("aadddza")) # Output: a2d3z1a1 (matches your expected result) print(string_compress("HelloWorld")) # Output: h1e1l2o1w1o1r1l1d1 print(string_compress("")) # Output: "" (no crash!)
This version is cleaner, more efficient, and follows Python's best practices while keeping your core compression logic intact.
内容的提问来源于stack exchange,提问作者ArtfulRefraction

