Filling a Workflow Gap with bpython

Posted in December 2020 to workflow

I felt a bit disingenuous putting this article under the category of "programming", as it's more a discussion of workflows used for programming than actual programming itself. However, can I really justify having an entire category for "workflow"? We shall see.

This time, I'd like to share my experience with bpython, an alternative Python interpreter. I first installed bpython a few months ago, but only started playing around with it today. Up until now, I've only used the standard Python interpreter. While I haven't had any particular problems with it, I've felt like there was a gap in how I worked. As far as I'm aware, there isn't an easy way to edit your session history, or to save the output to a file. As a result, I've only used the Python interpreter to do simple checks of one-line commands. Anything that involves writing a function feels like too much hassle, because I can't edit the history afterwards if I make a mistake, or save it to a file. While it's also possible to do work in vim, I feel as though this lacks the immediacy of using an interpreter.

My other recent go-to has been Jupyter. Being able to whip up graphics quickly and in the same window is a big plus, as is being able to re-run your code after editing it. However, this too is something that I probably wouldn't use if I just need a quick solution to something.

This time, I turned to bpython to help me solve this problem:

A lot of n items contains k defectives, and m are selected randomly and inspected. How should the value of m be chosen so that the probability that at least one defective item turns up is .90?

Mathematical Statistics and Data Analysis, Rice, 3Ed

I wanted to write a simple function to solve this, but at the same time, I recognised that there might be fiddly bits that I'd have to go back and edit.

I had a tentative go at writing the function line-by-line in the bpython interpreter, and as expected, it didn't work first time. But a quick search of the bpython docs revealed its hidden weapon: press F7 and you can edit your session history! I fixed the issue with the program and then ran it again (and repeated a few times until it worked properly), and this was the final result:

### current bpython session - make changes and save to reevaluate session.
### lines beginning with ### will be ignored.
### To return to bpython without reevaluating make no changes to this file
### or save an empty file.
from math import comb


def check_count(Q, n, k):
    """
       Return the number of tests necessary to find one or more of k defective 
       items in a lot of size n with probability Q.
    """
    for poss_m in range(1, n):
        total = 0
        for i in range(1, k):
            if poss_m >= i:
                total += comb(k, i) * comb(n-k, poss_m-i)
            else:
                total += comb(k, i)
        if (out := total / comb(n, poss_m)) >= 1:
            pass
        elif out > Q:
            return poss_m

check_count(0.9, 1000, 10)
# OUT: 205
check_count(0.9, 10000, 100)
# OUT: 227
### 

One of the other cool things is that bpython will show the docstring of a program while you're typing. Here, it's showing the docstring for the program I just wrote:

>>> check_count(
┌───────────────────────────────────────────────────────────────────────────┐
│ check_count: (Q, n, k)                                                    │
│ Return the number of tests necessary to find one or more of k defective   │
│ items in a lot of size n with probability Q.                              │
└───────────────────────────────────────────────────────────────────────────┘

Another interesting thing is the F8 shortcut, which uploads the session history to a pastebin so you can share it online. Now I've finally gotten started with bpython, I'm excited to explore some of its other features!