如何基于DRY原则精简这段存在重复代码的Python函数?
create_post Function with DRY Principles Hey there! Nice job catching that repetitive code in your create_post function—sticking to the DRY (Don’t Repeat Yourself) principle will make your code way easier to maintain, debug, and extend later on. Let’s walk through how to streamline this.
The Problem: Duplicate Logic
Your if and elif branches are almost identical—only the line where you fetch the file_id changes. All the file downloading, temporary storage, and API request code is copied verbatim, which means if you ever need to update that logic (like changing the temp filename, fixing headers, or adjusting the API payload), you’d have to do it in two places.
The Solution: Extract Reusable Code
We can split the function into two parts:
- A helper function to handle the unique part (getting the correct
file_idbased on content type) - Keep the shared logic in the main
create_postfunction
Here’s the refactored code:
def create_post(filename): # Get the correct file_id using our helper function file_id = get_content_file_id(filename) # Shared logic for downloading the file file = bot.get_file(file_id) downloaded_file = bot.download_file(file.file_path) # Save the file (note: you might want to use a dynamic filename for videos, see below) temp_file = "image.jpg" with open(temp_file, 'wb') as new_file: new_file.write(downloaded_file) # Process the file and send the API request token = store_file_temporary(temp_file) # Fixed duplicate Content-Type header (you had two conflicting values!) headers = { "Accept": "application/json", "Content-Type": "application/json" } payload = { "title": randomString(), "safety": 'safe', "contentToken": token } response = requests.post( url=f"{url}/posts/", json=payload, auth=(username, password), headers=headers ) print(response.json()) return response.json() def get_content_file_id(filename): """Helper to fetch file_id based on content type""" content_type = filename.content_type if content_type == 'photo': return filename.photo[-1].file_id elif content_type == 'video': return filename.video.file_id # Add a fallback for unsupported types to catch errors early raise ValueError(f"Unsupported content type: {content_type}")
Key Improvements
- Single Source of Truth: All the shared logic lives in one place—no more copying and pasting changes across branches.
- Separation of Concerns: The helper function
get_content_file_idonly handles fetching the right file ID, whilecreate_postfocuses on the end-to-end workflow. - Fixed Header Conflict: Your original headers had two conflicting
Content-Typevalues (multipart/form-dataandapplication/json). Since we’re usingjson=payload, Requests automatically sets the correctContent-Type, so we only keep the necessary headers. - Error Handling: Added a
ValueErrorfor unsupported content types—this will help you catch issues early if someone passes a content type your function doesn’t handle.
Bonus: Dynamic Temporary Filenames
Right now, you’re saving both photos and videos as image.jpg, which might cause unexpected behavior (like overwriting a photo with a video). You can fix this by using a dynamic filename based on content type:
# Replace the temp_file line in create_post temp_file = f"temp_{filename.content_type}.{'jpg' if filename.content_type == 'photo' else 'mp4'}"
And if you want to clean up the temporary file after processing (to avoid cluttering your filesystem), add this after calling store_file_temporary:
import os os.remove(temp_file)
Final Thoughts
This refactor makes your code cleaner, more maintainable, and true to the DRY principle. If you ever need to add support for another content type (like audio), you just add a new branch to get_content_file_id—no need to duplicate all the other code!
内容的提问来源于stack exchange,提问作者Fatih Akgun

