2025 in Media

(Post theme: friendly fire (the pool song)).

This year, I watched 164 films. I recommend Tinā, KPop Demon Hunters, The Gorge, Swiped, Python: The Documentary, Girl Haunts Boy, and We Live in Time, and Sinners. A somewhat disappointing year for films for me.

I also watched 1,259 episodes of TV. I recommend Taskmaster, The Runarounds, Murderbot, Department Q, and Shrinking. Not a great year for TV, either – a lot of stuff I’m somewhat interested in watching, but nothing that really grabbed me.

On YouTube, I watched a lot more than in previous years. I recommend the Taskmaster Podcast, the TalkVille Podcast, Nikki Lu, Dish Podcast, and Off Menu.

I listened to 158 hours of podcasts (this is roughly how long I spent travelling, since that’s about the only time I listen to podcasts these days). I recommend The Morning Shift, the Taskmaster Podcast (again), Gone By Lunchtime, Juggernaut, Wait Where Was I, and The Long Play.

I listened to 3,158 songs (around 64,000 minutes) this year, up quite a bit from last year (mostly because I was living alone for most of the year – it is very quiet!). I recommend Kids Up The Tree, Cassie Henderson, fdasavage, aleksiah, Borderline, Little Green, Emei, Maddy Low, Fan Club, Phoebe Grace, Brooke Alexx, Daisy Grenade, Chloe Parché, and LØLØ. A really great year for discovering new music.

I read a lot of stuff online (via RSS). I recommend everything I posted to tonyandrewmeyer.blog, and in particular: The Spinoff, Simon Willison, Armin Ronacher, and Charity Majors.

I read 115 books (including paper, ebooks, and audio books) this year (a bit over 47,000 pages). I recommend The Staff Engineer’s Path: A Guide for Individual Contributors Navigating Growth and Change, most of Brandon Sanderson‘s books, The Thursday Murder Club, The Library Trilogy, The Witch Roads, The Final Architecture, and Violet and the Velvets: The Case of the Missing Stuff. A good year for enjoyable books, but missing anything that really wowed me, unfortunately. A good book club year again, and a good year of re-reading some childhood favourites (not all of which stand up).

Happy new year!

Review: Help! I Have a Manager! – Wizard Zines

(Post theme: Talk by Coldplay)

Next up in the Wizard Zines set is an odd one, not being particularly technical, and I think one of the earlier ones: Help! I Have a Manager, which is all about building good relationships with your manager.

Like Julia, I’ve had several good or great managers, and a few not so much. I have found them all very different, so page 16, which is all about this, really resonated. Other than that, this was pretty much all advice I’d seen elsewhere and/or picked up naturally. For someone really early career, this might be worthwhile, but I’d skip it otherwise.

Unlike the other zines, this one (at least the PDFs, when viewed in Apple Books) had weird spacing issues where text had odd gaps and sometimes had overlaid characters. Not enough to prevent reading the zine, but enough that it doesn’t feel polished like the others.

Review: Bite Size Bash – Wizard Zines

(Post theme: Hall of Fame (feat. will.i.am) by The Script)

As mentioned previously, I purchased the set of Wizard Zines via my annual training budget, and am working through them. Current reading: Bite Size Bash.

The first 20 pages surprised me – I don’t consider myself particularly knowledgeable in terms of bash (or similar shell scripting) but pretty much everything in the basics I’ve managed to somehow pick up over the last couple of decades, despite usually jumping pretty quickly into another tool whenever my needs get above simple. It is a great intro, though, and I would have benefited having this at hand years back.

On page 20, parameter expansion is introduced. Most of this was either new to me, or I think I’ve seen but certainly wouldn’t remember to use. I’m not sure how to make this stick, though – the syntax is so odd. Maybe I should just jump to this page next time I’m writing bash, or maybe I’ll remember that it can be done and that will be enough to look it up or remember. I do wonder if LLM will replace this sort of learned syntax, though.

After that, it was background processes and subshells, both of which were again surprisingly familiar. After that is trapping signals – I knew this could be done, but I’m pretty sure by the time I have something that needs to do this, I’ve already moved to another language, and I don’t see that changing. Errors and debugging were also mostly things I knew, except for ‘trap x DEBUG’, which seems pretty handy.

Overall, this zine surprised me: I expected to learn a lot, and instead recognised a lot. In some ways, this is great: I feel more confident that I do actually know the most useful core of shell scripting (even though certainly not the vast area beyond that). I’d definitely recommend it for shell scripting beginners (especially bash) but likely not for others.

Review: Become a SELECT Star – Wizard Zines

(Post theme: Call Off the Search by Katie Melua)

As part of my training allowance for 2024, I purchased all 14 of Julia Evan‘s zines. There are definitely ones I expect to learn from more than others, but having the pack appealed, and one of the things I really enjoy about her posts is finding little tidbits of information that I didn’t know, even though I would have said I know the topic fairly well in general.

First up: Become a SELECT Star, which, as you’d guess from the title, is all about the SELECT statement in SQL. The first dozen pages are a really good summary of the fundamentals: things that I gradually absorbed over the last 20 or so years, and probably would have been better off with having a summary like this rather than a bunch of more traditional reference material.

I really like how the examples work through the query in the logical order rather than the syntax order. It makes it much simpler to follow what’s happening.

On pages 14-16, it covers window functions, which I didn’t really know at all. I would normally just do this by getting a bunch of the data down into something like Python and calculating there. I’m a big fan of moving computation left where possible, so these seems super useful, and something I hope I remember (although I don’t do a huge amount of SQL these days).

The zine continues on to cover NULL and COALESCE, which we used a lot at SpamExperts, so those were pretty familiar, but again a good summary that I could have used many years back! It then covers CASE, and I don’t remember if I knew that or not, but also don’t think I can think of times I would have wanted it directly in SQL.

After a straightforward page on counting rows, it moves into subqueries. I’ve used these quite often (I’ve often had situations where subquery performance was better than joining, for various reasons). However, common table expressions (naming sub queries) is new to me, and look super useful.

It wraps up with a few more useful tips, most of which were things I already knew.

I’d definitely recommend this to anyone that’s just starting with SQL. If you’re a SQL expert, it’s likely not going to be useful, but if you’re a casual querier like myself, then there are good tips to pick up, and given how small and inexpensive the zine is, I’d highly recommend picking it up.

GitHub “sync fork” silently failing

(Post theme: Oops! I Did It Again by Britney Spears)

Posting because I’ve hit this three times now and each time not remembered the solution until I figured it out again, in the hopes that writing it down will prompt my memory next time and avoid a fourth “figure it out fresh” cycle.

At work (in the team I’m on), we develop in the open using public Github repositories. To introduce a change, we fork the repo, create a branch, and submit pull requests to the upstream main branch.

As changes make their way into main, it’s handy to be branching off an up-to-date fork, and GitHub has a convenient “sync fork” tool in the web UI to do this. Most of the time, this works perfectly. Unfortunately, a few times I’ve tried to sync and it silently fails (the cause is user error, but the silent nature of the fail is very poor UX from GitHub, and I feel like they could actually make the whole process work, which would be ideal UX).

The reason it has failed (each time it has happened to me) is that branch protection is enabled for the main branch on the fork. I’ve enabled this to avoid accidentally pushing changes to main (forgetting to create a branch first), which I never want to do – except for pulling in upstream changes.

There might be a simpler way to work around this (other than opening a PR from upstream main to the fork main) but I just disable the protection, sync, then enable it again.

Mobile Phones at Mahurangi College – Feedback

(Post theme: The Times They Are-A-Changin’ by Bob Dylan)

This is a copy of the feedback I provided to Mahurangi College in response to this consultation request:

The Government has introduced regulations that require all state schools to have student phone rules in use. Rules must be in use as soon as possible in Term 1 2024 and no later than Term 2.

Many countries around the world have successfully banned mobile phones in classrooms, or are in the process of doing so. A solid body of evidence is emerging that supports the banning of phones in schools. 

Our draft policy and notes are included here, as well as a space for you to provide some feedback.

So far this term our approach has been to educate – students have had the rules clearly explained, and lots of reminders and warnings have been given. The vast majority of students have adapted very well.

Following your feedback, we will finalise and publish our final policy.

Mahurangi College, February 2024

I understand that the requirement to have a policy has come from the central government, which puts some constraints on what the school can do. However, I had hope that the school would show more courage and defy poor decision making as much as possible. Given that ERO is responsible for monitoring the implementation of these policies, at worst the school would receive a negative comment in a rarely-read review, and by the time the next review cycle came around, it’s likely that a government less interested in pandering to racist, anti-science, scared, old people would be in power.

Any form of defiance would suffice, but I like following the letter of the regulation rather than the intent. The iPhone is famously “an iPod, a phone, and an Internet communicator”, and Android phones are widely recognised as being functionally equivalent to iPhones. Students must not be allowed to use or access a phone – but there are no rules about iPods or internet communicators. The answer is clearly that the Phone app on mobile devices must be banned, but using the rest of the device is fine (you could even use a device management profile to disable the Phone app while at school).

This is logically consistent, since students are not only allowed but expected to have other digital devices (such as a laptop), which has exactly the same internet communication functionality (indeed: the permitted smart watches, laptops, tablets, and other devices are essentially the same device as a phone – often running variants of the same operating system on the same chips – just in a different form factor).

Under no circumstances should phones be used to photograph or film any student or member of staff without their permission, or to film any fights or skirmishes.

Mahurangi College Draft Policy

For the record, I have no objection to this as a policy statement, although I would suggest that it’s mistakenly placed in a “mobile phone” policy, given that there are many other devices (and a class that is specifically focused on learning how to use them well) that are capable of photographing or filming a student, and the choice of device is entirely irrelevant.

  • Headphones & earbuds also cannot be used at school (apart from on buses) as they require connection to a mobile phone.
Mahurangi College Draft Policy

It’s hard to believe that this passed any sort of quality control. Did you have a junior student write it? I would expect that anyone old enough to work at the school would be familiar with a multitude of devices with which headphones (whether in earbud form or otherwise) can be used. Perhaps the staff might remember using headphones with a record player, Walkman, or Discman? Perhaps some of the staff are familiar with the school’s own requirement that students do have headphones so that they can consume media during class without disturbing other students? Was the author of this policy aware that the school offers classes in music, dance, and media studies, and that film is studied in many of the English classes? Did they know that the laptops that the school requires students have almost universally work with headphones? Given the conflicting policies, which one wins out?

Perhaps you’d consider looking at the actual science? For example, a 2023 study that showed that students using smartphones outperformed those without (Wang, J.C., Hsieh, CY. & Kung, SH. The impact of smartphone use on learning effectiveness: A case study of primary school students. Educ Inf Technol 28, 6287–6320 (2023). https://doi.org/10.1007/s10639-022-11430-9), or the Harvard Graduate School of Education who say that more thought needs to be applied rather than simple bans. Closer to home, Massey University educators clearly state that bans are not the right choice. Or look at meta-studies (for example: Calderón-Garrido, Diego & Ramos-Pardo, Francisco & Suárez-Guerrero, C.. (2022). The Use of Mobile Phones in Classrooms: A Systematic Review. International Journal of Emerging Technologies in Learning (iJET). 17. 194-209. 10.3991/ijet.v17i06.29181), which show benefits in the use of phones at school.

It should be obvious that the ability to have at hand a device that is a calculator, a compass, an e-book reader, a still and video camera, a research tool that would be considered magical even a few decades ago that provides access to nearly all the world’s information, that tracks and provides advice for improvement of health, a torch, a measuring tape, a glimpse into virtual and augmented reality, that receives emergency alerts, and much more is of huge value to a student. Instead of harming their educational development (and providing an environment irrationally different from the world they will enter at the conclusion of secondary school) you should be figuring out ways to make sure that those students who do not have phones are able to use one.

I have no objection to behaviour management, whether during class time or during breaks on the school property or on school trips. If someone is misusing a phone – or anything else – in a way that disrupts their or other students’ learning, then that should be remedied appropriately.

I’m also tolerant of prohibiting access to specific internet properties (TikTok, Instagram, Snapchat, and so on), although I do believe that in time prohibition will be demonstrated to a poor approach to the problems that these sites exacerbate.

I have no hope at all that the school will reconsider this policy (although a little hope that someone will realise that headphones can be used with devices other than phones), particularly given the numerous other policies that are clearly either anti-learning or irrelevant to learning. However, I offer this feedback anyway, so that at least you will have heard how wrong you are.

Writing as a metaphor for coding

At work, our book club is reading Code Complete, and had our first discussion session today. I first read this in early 2011 – roughly 6 years into professional software development – and remember thinking quite positively of it at the time. We’re only three chapters in, but I’m decidedly more mixed on it this time around – I’ve had a lot more varied experience with development projects than in those early years, and a lot of the book lands quite differently (I do suspect that the later chapters will have stood the test of time better).

The second chapter of the book is focused on the importance of choosing a metaphor for software development – it ends strongly suggesting that building construction is an elegant metaphor. I agree that metaphor can be useful (but is also easily overused, and people get fixated with the imperfection of the chosen metaphor – “But if you extend them too far or in the wrong direction, they’ll mislead you”, as the author says) and that construction can work as one for software development.

However, the author, says:

For an individual’s work or for small-scale projects, the letter-writing metaphor works adequately, but for other purposes it leaves the party early—it doesn’t describe software development fully or adequately.

Steve McConnell, Code Complete, Chapter 2 “Software Penmanship: Writing Code”

This struck me as deeply ironic. Writing is an excellent metaphor for software development, and the author of a book – especially a large technical one – should be extremely aware of this.

The author seems to only consider the analogy of the metaphor to be of “writing a casual letter”, rather than writing in general. This is unfair to the metaphor and not applied to that of construction (which covers all sizes, not just flat-pack assembly). Writing ranges from a succinct social media post to a collection of textbooks or connected story that ranges over dozens over books by multiple authors (Wild Cards, Cosmere, Marvel, Riftwar, to name a few). This is hardly unique to writing – construction, farming, and other metaphors the chapter explore all range in sizes.

Writing is usually a one-person activity, whereas a software project will most likely involve many people with many different responsibilities.

Steve McConnell, Code Complete, Chapter 2

This quote was particularly interesting, as one of my colleagues brought it up in our discussion as an example of how McConnell was correct about writing being a poor metaphor, whereas I read it as an example of how wrong he was.

The “many people with many different responsibilities” absolutely applies to (non letter!) writing – you have editors, alpha and beta readers, illustrators, publicists, and many more. A lot of these work well in the software development metaphor – early readers are code reviewers, illustrators are designers, publicists are, well, publicists, and so on. This is the aspect that I was focused on when I read it.

My colleague, however, saw the truth in the “one-person activity”. It’s true that a lot of writing is done by one person. There are a lot of examples where this is not the case (co-authoring, anthologies, shared universes, ghostwriting, a lot of journalism, etc), but it’s probably safe to say that there’s less cowriting (particularly of the same block of text, however you define “block”) in code than other writing. I think where we differ is that I see this as one area where the metaphor is weak, but the rest is so strong that it outweighs that.

I also do suspect that that there’s an awful lot of software that is written by a single person. This isn’t just sole-developer products, but also components of large, multi-person, systems where there’s a single person that does nearly all the writing and maintenance of that one component (or module or library or micro-service or …). This isn’t good software development, but in my experience it is, unfortunately, fairly common. Often there are other people involved, but only lightly, in the same way that an editor or sub-editor might be with other writing.

In writing, a high premium is placed on originality. In software construction, trying to create truly original work is often less effective than focusing on the reuse of design ideas, code, and test cases from previous projects.

Steve McConnell, Code Complete, Chapter 2

I’m not sure that originality is that much of a premium in letter writing – but then I never did much of that. More broadly, originality has a “premium” in some forms of writing, but not in others – people are generally looking for the same broad style in a new romance novel, they find it easiest to read news articles that are structured in the same way, the latest Reacher novel is not that different from the previous one (or the last Will Robie, or the last Alex Cross, and so on)1.

There’s a concept in software development that you get three “innovation tokens”. Similarly, when writing a novel or series of novels, you can have a truly original character, or world, or plot, or theme, but you almost always need to have the majority of the work be fairly familiar to the reader (particularly a reader who is familiar with the genre). Just as with software development, you can go wild with innovation and originality, but it’s high risk and makes it harder for readers/users.

When you finish writing a letter, you stuff it into an envelope and mail it. You can’t change it anymore, and for all intents and purposes it’s complete.

Steve McConnell, Code Complete, Chapter 2

This is true of a letter, but untrue of most modern writing. Pushing the irony more, this is a quote from the second edition of Code Complete. Writing that ends up in print often is in a final form – but there’s also a lot of software out there that just runs without any updates.

To be fair to McConnell, 30 years ago there was a lot less revision of writing – no editing Wikipedia, pushing out ebook updates, rapidly revised news articles, or tweaked blog posts. On the other hand, there was also a lot of “finalised” software back then too, where you’d buy a box with a disk or cartridge and, unless you did buy an updated version, you’d have that same version forever.

But extending the metaphor of “writing” software to a plan to throw one away is poor advice for software development, where a major system already costs as much as a 10-story office building or an ocean liner.

Steve McConnell, Code Complete, Chapter 2

I’m very much in favour of a reasonable level of well-executed planning and design, but beginning a software project without being willing to throw away any dead ends would strike me as a huge red flag. Defining the role of a software architect is complicated (see also this great Charity Majors post) but I maintain that the core task of an architect is working with people to minimise the number of decisions that are regretted in the future. That might be a wonderful design where almost nothing is thrown away. It might also be settings things up so that throwing things away is inexpensive and experimentation leads to market success.

I’d argue that with the really huge projects, we have plenty of examples (Novopay, INCIS, and others just in Aotearoa New Zealand) that show that big upfront planning with a reluctance to throw anything away leads to terrible cost overruns and missed deadlines.

Building software implies various stages of planning, preparation, and execution that vary in kind and degree depending on what’s being built.

Steve McConnell, Code Complete, Chapter 2

This is exactly what writing is like. Just like when writing a small “throw-away” software script, almost no planning goes into a social media post. When writing a novel, there’s a huge amount of planning, preparation, and execution (here’s a series going into it from one author – there are many, many, others – books on how to write books are almost as common as podcasts about making podcasts!). I find it difficult to believe that this was not the case for writing Code Complete itself.

McConnell extends that argument to compare the cost of making a mistake on a small project with one on a large project (ignoring any learning that may have come from making the mistake) – this equally applies in writing. If I end up rewriting a section of a blog post, that’s fairly trivial. If I have to restructure the entire third act of a novel, that’s a bigger issue, and if I have already finished two books in a trilogy and need to make changes to them to make the final volume complete, that’s very expensive to fix.

In building a house, you won’t try to build things you can buy already built. You’ll buy a washer and dryer, dishwasher, refrigerator, and freezer. Unless you’re a mechanical wizard, you won’t consider building them yourself. You’ll also buy prefabricated cabinets, counters, windows, doors, and bathroom fixtures. If you’re building a software system, you’ll do the same thing. You’ll make extensive use of high-level language features rather than writing your own operating-system-level code.

Steve McConnell, Code Complete, Chapter 2

When writing a novel, you don’t start from first principles. You’ll probably have a three-act structure, your story probably fits – at least somewhat – into one of seven basic plots, and you’ll build on top of whatever tropes are appropriate to the world you’re writing about. You don’t need to explain enemies-to-lovers or the misdirects in a mystery story, and you can call your Hobbits “halflings” and most readers will immediately have the right characteristics to mind. Just as in McConnell’s example of luxury housing having some of these fittings custom-made, the highest quality novels often deviate from the norms in a few specific areas (an imaginative magic system, a innovative take on local history, an unusual prediction about the future, and so on).

Finally, the construction analogy provides insight into extremely large software projects. … [Builders] build in margins of safety; it’s better to pay 10 percent more for stronger material than to have a skyscraper fall over. A great deal of attention is paid to timing. When the Empire State Building was built, each delivery truck had a 15-minute margin in which to make its delivery. If a truck wasn’t in place at the right time, the whole project was delayed.

Steve McConnell, Code Complete, Chapter 2

Cost and timing are important in extremely large writing projects too. Delays in editing or proofing or illustration or printing or many other things can delay an entire book launch (the Potter books have apparently reached nearly US$8B in sales, the Empire State Building cost under US$1B to build, adjusted for inflation). When a book is very high profile, it’s worth spending extra to have additional early readers and editors, just as you build with stronger material (obviously an unsuccessful book is less significant than a collapsing building).

Overall, I do agree with some of the core takeaways of the second chapter – that there’s value in metaphor, that they are “a little sloppy”, and that you should use the best (mix) of metaphors that work in the context. I just can’t agree that construction is a better metaphor for writing code than writing (non-code) is.

This chapter might have hit the sweet spot for me – the combination of reading/writing and software development – but I’m hopeful that the upcoming ones will also be as thought-provoking and enjoyable to discuss with my colleagues. If you don’t have a work book club, I highly recommend starting one! (Non-work book clubs are great too!).

  1. To be clear: I really enjoy a good romance novel and all of the book series listed there. The familiarity has the same comfort as a good TV procedural or film sequel. ↩︎

Inconsistent public service efficiency

(Post theme: drivers license by Olivia Rodrigo)

I renewed my driver’s license last week (having turned 45 recently) and it was striking how different the experience was to the other common government-issued identification: a passport. New Zealand’s passport service, Te Mata Uruwhenua, (run by Te Tari Taiwhenua the Department of Internal Affairs) is remarkably efficient – everything from the application process through to delivery is handled extremely well. They promise reasonable process times, and almost always better them.

Last Friday, on the other hand, despite arriving less than 15 minutes after they opened, I had a 30 minute wait for someone to spend less than five minutes reviewing a form, take a photo, and provide an image of a signature.

There are a lot of flaws in the system, such as:

  • Why not have the form available online? Presumably someone is going to be entering the relevant details into a digital system anyway. The passport renewal process is entirely digital.
  • What benefit is there in requiring physical possession of the expiring license? They have all this data in the system, obviously, so if they wanted to check that I looked like the 10-year-old photo, they have that already. No-one checked my signature. Having the card doesn’t prove identity – I could have picked it up off the street. I didn’t have to go anywhere or show my old passport to renew it. Sadly, an elderly lady in front of me in the queue, who had travelled almost an hour to get there, had forgotten her old license and had to get rejected at the counter.
  • Why take the photo there rather than just providing one? That works for passports, where the requirements are much more strict. This could easily be part of the submission process.
  • I’m not particularly convinced that the written signature provides much value, but even if it’s needed, this is done on some sort of digital system anyway, so could also easily be done as part of a submission.
  • My expiring license was invalidated (it had about 6 weeks left) and replaced with a paper temporary license that lasts for 3 weeks (which will be tight to get the new one in the post, but that’s a separate rural post issue). Why not just leave me with the old one until the new one arrives?
  • Why is someone manually checking a form anyway? The address checks were making sure they matched the ones on file (both inaccurate anyway, with the regular address wrongly including the rural delivery number, and the mailing one not matching the form NZ Post likes), which is trivially automated. The other details would similarly be simple to check by a system.

It’s strange to have one service work so well and one so poorly but easily improved. Can’t we just loan some people from Te Mata Uruwhenua to Waka Kotahi NZTA to get things improved?

Asking ChatGPT for help, take 2

(Post theme: With a Little Help From My Friends by Joe Cocker)

People (at lunch) at Kiwi PyCon were praising ChatGPT as a tool to help write code more efficiently, so I had another go.

I recently moved a Django project to use Whitenoise, and more specifically to have manifest files, where the version is appended to the collected file names. This all works great, except that there are a few files that users download, and instead of getting, for example, template.xlsx, they were getting template.{md5hash}.xlsx.

I asked how to have the file downloaded with the original name, rather than the one with the version hash. In retrospect, I realise I asked the wrong question, because this is an HTML question not a Django staticfiles one, but I hadn’t thought about it enough at the time, and, anyway, surely the assistant is meant to pick up on that.

The answer told me to use the ‘as’ functionality of the static tag, but that’s completely wrong. That’s to get the URL into a variable to use in the template.

To be fair, it then did give the correct answer, that the download attribute of the a tag should be used. So I guess I’d give this a B- grade, for getting the solution but confusing it with a bunch of irrelevant info first.

Python return styles

I was reading through the charmed tech ops code today and noticed a bunch of code like:

def f():
    if check:
        return val
    else:
        return None

I don’t particularly love this (although I do feel you should match the style of an existing code base and should avoid changes that don’t meet a reasonable level of value-add). I would generally leave out the else (and dedent the second return). It seemed likely that these generate the same opcodes so this is purely about readability, but it was worth checking that:

>>> def f1(a):
...   if a == 1:
...     return 'A'
...   else:
...     return None
... 
>>> def f2(a):
...   if a == 1:
...     return 'A'
...   return None
... 
>>> def f3(a):
...   return 'A' if a == 1 else None
... 
>>> def f4(a):
...   if a == 1:
...     return 'A'
... 
>>> dis.dis(f1)
  1           0 RESUME                   0
  2           2 LOAD_FAST                0 (a)
              4 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
             12 POP_JUMP_FORWARD_IF_FALSE     2 (to 18)
  3          14 LOAD_CONST               2 ('A')
             16 RETURN_VALUE
  5     >>   18 LOAD_CONST               0 (None)
             20 RETURN_VALUE
>>> dis.dis(f2)
  1           0 RESUME                   0
  2           2 LOAD_FAST                0 (a)
              4 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
             12 POP_JUMP_FORWARD_IF_FALSE     2 (to 18)
  3          14 LOAD_CONST               2 ('A')
             16 RETURN_VALUE
  4     >>   18 LOAD_CONST               0 (None)
             20 RETURN_VALUE
>>> dis.dis(f3)
  1           0 RESUME                   0
  2           2 LOAD_FAST                0 (a)
              4 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
             12 POP_JUMP_FORWARD_IF_FALSE     2 (to 18)
             14 LOAD_CONST               2 ('A')
             16 JUMP_FORWARD             1 (to 20)
        >>   18 LOAD_CONST               0 (None)
        >>   20 RETURN_VALUE
>>> dis.dis(f4)
  1           0 RESUME                   0
  2           2 LOAD_FAST                0 (a)
              4 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
             12 POP_JUMP_FORWARD_IF_FALSE     2 (to 18)
  3          14 LOAD_CONST               2 ('A')
             16 RETURN_VALUE
  2     >>   18 LOAD_CONST               0 (None)
             20 RETURN_VALUE
>>> 

Interestingly, there is one difference out of those four variants, where instead of a second RETURN_VALUE op, there’s a JUMP_FORWARD to the single RETURN_VALUE. I assume that means that it’s slower in a way that’s so imperceptible that it’s not worth caring about, but let’s check:

>>> timeit.Timer("f(random.random())", setup="import random\ndef f(x): 'a' if x > 0.5 else 'b'").timeit(10000000)
1.4031157046556473
>>> timeit.Timer("f(random.random())", setup="import random\ndef f(x):\n if x > 0.5:\n  return 'a'\n else:\n  return 'b'").timeit(10000000)
1.326032117009163

I feel this does land in the expected place, where it’s about style & readability. I suppose f1() explicitly shows that it’s making a choice between two cases, but I feel that’s countered by f2() and f3() showing that the function returns a value. In general, it’s nice to have the smallest amount of indentation, so I would not choose to use f1().

Between f2() and f3(), I would generally choose the single-line approach of f3() if the line didn’t wrap (or exceed whatever the wrapping length is for the project, e.g. 100 characters). I would not do this:

def f3_alt():
    return (
        really_really_really_really_really_really_really_long_val
        if another_very_very_very_very_long_condition
        else also_quite_long_here_and_now_we_wrap
    )

If you’re doing this, then there’s no benefit over the f2() style (and, as it turns out, there is a very tiny performance penalty).

Python has an implicit return None at the end of a method that doesn’t otherwise return. This means that for this specific case, where one of the values is None, there’s also the choice between f2() and f4(). In reality, f4() would be slightly better than it is here, in that it would probably have a return type (with |None) and a docstring that explains that None is a possible return value. However, I still (weakly) prefer f2() where it’s called out explicitly rather than f4() where you need to know that this is what Python does.