From Spark to Publication (Ep. 20)
The lifecycle of my most recent Python article • The process, decisions, reasons…
Normally, I write about my ideas around making technical writing more narrative. However, in this post, I will write from a more practical perspective.
Today, I published my latest article on The Python Coding Stack. It's not an extensive tutorial about a fundamental topic in Python. Instead, it deals with a relatively minor observation about a useful but hardly exciting Python tool.
As I planned and wrote the article, I kept a record of all the steps, thought processes, considerations, deliberations, and decisions that led from that initial spark of an idea to hitting the Publish button. This post presents this process.
I'm very aware that many of my Breaking the Rules readers aren't Python programmers. Python knowledge is not required to follow this post. I'd also recommend reading the main Python article before continuing with this post. It's not a long article, and you'll follow most of it even without Python knowledge. Here it is: https://www.thepythoncodingstack.com/p/counting-in-python-list-count-how-hard-can-it-be
And join me for more discussions about technical writing in the Breaking the Rules forum
WTW • Every article starts with the WTW stage–What to Write?
I was recently teaching a live session, and the discussions led to a somewhat unexpected result. A straightforward command to count how many times an item appeared in a collection seemed to give the wrong count.
The discussion leading to the reason behind this apparent counting error and how to fix it was revealing, and it showcased key aspects of how Python works behind the scenes.
Soon after the live session ended, I jotted down this thought in the Ideas column on the Kanban board I use to track my articles. This is the leftmost column on this board. It's where all articles start.
Summary of the technical topic: The Python instruction .count()
is linked to a list of items, and it returns the number of times a specific item appears in that list. But when the items in the list are of a type defined by the programmer, Python may not know how to group similar ones together. So, it may fail to give the "right" answer.
Brewing • The brewing stage is when I develop my ideas. This is when the article takes shape, even though I rarely write a single word down during this phase.
On the face of it, the topic for this Python article is rather dry. It deals with counting objects and why Python sometimes "gets it wrong." [Spoiler alert: it doesn't.]
But there's always something interesting if you look deep enough. This is the direction the discussion took in the live session that led to this article idea. This topic felt like one that could benefit from story-framing. [More on story-framing in chapter six of the Breaking the Rules book]
But it's also one that could benefit from narration techniques applied directly to the technical details. [And there's more on narrating the technical details in chapter seven of the Breaking the Rules book]
Deciding early on what narrative techniques I wish to use is important as it gives me a good idea of what type of article it will be. In this case, story-framing was going to be the primary narrative tool. That means I need to find a story to fit the main point of the article. The story isn't just a bit of fun on the side. It needs to help communicate the technical content.
I let these ideas brew in my head over several days. I thought about it while getting on with other things, going for a walk, brushing my teeth, whenever I could spare some brain processing power. The next few sections in this article are also part of the broader brewing stage.
Choosing the narrative • This is tricky. What story should I use? But the first question I ask myself is a different one: What's the story behind the Python issue I want to write about?
I find it useful to personify Python or the Python program and to link what's happening in Python to human traits, emotions, actions. Here's what this process looks like in this case—a reminder that a quick read of the Python article would be beneficial to understand my thought processes better:
Python didn't know how to group like objects together since these were objects the programmer had defined from scratch. So, Python interpreted the request as literally as possible and only looked for repetitions of the same object, not similar ones. But when the programmer clarified what Python should look for to determine whether objects are equal, Python had no issues returning the correct value.
Thinking of the program in human terms provides the first step towards creating a story. It provides the narrative for the story. Now, I needed an actual story to fit this narrative.
Choosing the story • More brewing is needed to get to a story. There's no magic trick to find the right story.
The first scenario that popped into my head was a weird one. But here it is: Two people standing in the street. One of them asks the other one to go around the block to count all the cars like that one while pointing at a car.
The other person goes round the block and then comes back, saying that's the only car like it. They're all a bit different in one way or another. But the first person then clarifies it's all the blue Ford cars he wanted him to count. Now that the task is clearer, the second person can count the number of cars that match those criteria.
But this didn't feel like the premise for a compelling story. Why would a person ask another one to count cars? Are they salespeople? Are they carrying out a survey? Are they thieves? I could have created a story from one of these ideas, but they didn't feel real enough.
So, I went back to the original premise–the basic one: A person asks another person to count something but doesn't give clear instructions on how to choose what to include in the group. Then, the issue is resolved with clear instructions.
I asked my family for ideas during dinner one day. I presented the premise above. We soon converged on food as the primary theme—probably because we were having dinner! We came up with the idea of a shop that sells food. So, I settled on a bakery or confectionery, and the food item that would take centre stage was a biscuit. I'll discuss one concern about this choice in the appendix below.
In the end, I chose to set the story in a patisserie just so I could use the alliteration The Python Patisserie (suggested by my son), even though patisseries don't usually sell biscuits.
Choosing the characters • Great! I now had the setting and the general idea of the story. Importantly, it was a story that fits with the key point of the article–a story that reflects the Python problem. Now, I had to fill in some details.
I needed characters. And even though I wasn't writing a novel, the characters still needed some, erm, character!
First up was the moderately annoying and fussy customer, Mr Bakeman, who wanted a particular type of biscuit. Mr Bakeman doesn't really contribute much to the story, but giving him some personal traits helps the reader picture the scene.
Then came the shop owner, Angie, and the new staff member, Todd. These come as a pair, as I'll explain below.
Todd, the new employee, didn't know much about biscuits. This point is important as it mirrors the idea that Python doesn't know the context when you ask it to count items it knows little about. In Python, you can create a class named
Biscuit
, but that won't mean anything to Python. That's the key difference between programming languages and humans. Todd's clueless nature fits this narrative well. But more on Todd later on.Angie, the patisserie's owner, is the one in charge. She's the one who knows what's happening. If Todd represents the Python program, Angie is the programmer. At first, she just points to a biscuit and asks Todd, "How many of that do we have?" But Todd takes her literally and says there's only one of that biscuit. Angie then clarifies that she's referring to biscuits with the two key characteristics: they're shortbreads and round.
More on Todd and Angie later.
Writing the code • My articles are about Python programming. Therefore, they include computer code. As you can imagine, this is a central part of the technical content.
In this case, the code was easy to write and followed naturally from the story. However, in other articles I write, the code can be more involved. The code and the story need to fit well with each other. So, I often need to revise the code and the story a few times to make sure they complement each other.
In longer articles with longer code sections, I often write the code twice. The first time, I just construct the code until I have a functioning version. Then, I re-write it with a didactic mindset, writing it the way I feel I should teach it rather than the way I would naturally write the code. This step often serves as a planning stage for the main body of the article.
However, I skipped this step for The Python Patisserie article as it wasn't required.
Write the story. Write the article • The hard work was done at this stage. By now, I had the code I was going to use and a very clear idea of what I was going to write and in what order. Personally, I prefer to write the article from beginning to end, starting with the introduction and then proceeding with all the sections in the same order they'll appear in the article.
I planned to write this article as a full story-framing post. In full story-framing, the story runs through the whole article, or nearly. In other articles, the story-framing may give way to sections that focus exclusively on the technical content without the story.
The key points I wanted to demonstrate were clear by this stage (I'll write these as technical points, which make sense from a Python perspective but may not make much sense to non-Python programmers):
.count()
will use the object identity to group items if.__eq__()
is missing.But it will use
.__eq__()
if it's available.
However, I also wanted to show an intermediate step–an example in which the same object is included more than once in a list to show that .count()
still counts it multiple times even if .__eq__()
is missing. I felt this was an important step in narrating the technical details, gradually building up to the final solution. But this raised a problem…
Swerving off course • This scenario doesn't make sense in my story. I used boxes with biscuits inside as the list of objects in my story. How can the same biscuit–the exact same biscuit–be in the box more than once? You could have a similar biscuit, but not the same one.
I didn't let this small inconvenience derail my entire story. So, I included a small section about an impossible box, one that somehow contains the same biscuit twice. It's a bit weird, a bit surreal, but this was a minor part of the article and I felt it's OK to put in this weird example.
However, if this was a major aspect of the topic, I would have to consider whether my story isn't appropriate after all. This is tricky. It's hard to scrap everything and start again from scratch when you discover a flaw in the story after you've invested time and effort crafting the narrative and possibly writing parts of the article. Luckily, this wasn't an issue in this case. But I have scrapped entire ideas in the past when I felt I was stretching the narrative too much, and the story may hinder rather than help.
Finishing off • The story-framing went through the whole article in this article. This isn't always the case. For more complex tutorials, I often limit the story-framing to the introduction and conclusion, with some anchors throughout the article.
Still, I wanted to dedicate the final sentences to the story rather than the technical detail. I often do this, but I had a further reason for this decision in this case.
In the article, I didn't explicitly state that Angie, the shop owner, represents the programmer and Todd, the employee who doesn't know much about biscuits, represents the Python program. I felt I didn't need to spell this out, and I could let the reader make this link.
However, in other articles, I may choose to make connections between the story and the technical content more explicit. This approach may blunt the literary sharpness of the story—it's always best to let the reader make such connections from a storytelling point of view. However, the primary aim of technical articles is to ensure the reader understands the technical topic. For this reason, I may choose to make any such connections clear to prioritise the didactic needs. The story takes a supporting role, unlike in a novel!
So, let's get to the final sentences in the article. Todd kept his job at the patisserie since when Angie learnt to communicate clearly with him, he was actually quite good at this job. Python will do what the programmer asks and wants if the programmer's code is clear and precise!
Appendix • Questions I thought about throughout the process • Here are some things I considered throughout the planning and writing process and the decisions I made:
Should I use biscuits as the key food item in the article? The word "biscuit" is one of those many words that have different meanings in different variants of English. What British English calls biscuits are cookies in US English, and biscuits are some other food items in the US. In this case, I chose to stick with the British focus as I don't think any confusion on what I mean by biscuit will detract from the story or its message.
And once I decided to keep using biscuits, I had to decide whether to write a note explaining the difference in terms and that I was referring to British biscuits in the article. Decision: I didn't add a note. I didn't feel it was necessary in this case. Notes and asides are great when they're needed, but they also distract from the main flow of the article. So, I only add them when I feel they're needed. I did make a compromise in the article—I linked the word shortbread to its Wikipedia page.
Technical point: Should I add a note that
.count()
isn't just a list method but a method common to all sequences? This fact would be one that many readers may not know, and it links well with Python's duck typing philosophy. In fact, it's an interesting point, so surely… No, I chose to leave it out, too. Reasons: I had three options. I could just mention this fact in passing without further explanation. But readers can find this approach frustrating. Or, I could explain the fact in a bit more detail, perhaps using three or four sentences. But this would take the reader off course. Is it worth the detour? I decided it wasn't. So, I went for the third option: I didn't mention it at all.Technical point: Should I explain
.__eq__()
in a bit more detail? I chose not to. I'll assume my reader knows about this special method. This is a call I make on a case-by-case basis in my articles. Sometimes I choose to explain the tools I use even when they're not central to the article, but I can't explain everything all the time. In this case, my decision was made easier as I wrote about this topic only two weeks earlier. My readers will know about.__eq__()
from that previous article and wouldn't want to read about it again.Technical point: When showing the example with
a_string
andanother_string
, which were both equal to"The Python Coding Stack"
, should I explain that this demo works with this particular string and in the manner I used it in my article, but may not work if the reader tries a different string or in a different environment? The issue here is rather technical and very much off-topic for the article. If the reader, say, uses a different string to the one I used in the article, a relatively short string without spaces or other punctuation marks (except the underscore), then CPython interns these strings, and the objects won't be different. Decision: I ignored this potential pitfall. It would be too much of a distraction from the main flow of the article. If a reader tries this with another string or in a different environment and it doesn't work, hopefully, they'll think of trying my code next! They can ask why theirs didn't work in the comments, and that will make for an interesting discussion. I also considered using lists instead of strings in this example. This pitfall disappears with lists. But I didn't want to confuse things since I needed to use a list to contain these two objects, the list I used to call.count()
. So, it's best to use a different data type within the list. And using another mutable data type would add complexity unnecessarily.Get a copy of my latest book, Breaking the Rules. Available in paperback or ebook…
I don’t publish too often on this Substack, but you can stay up-to-date and make sure you get each post by subscribing below…