The other week, I chatted with the fabulous Liz Starin and picked her aesthetically-enabled brain about fonts and layouts for websites. Below is some stuff I learned from our design adventures, both wisdom straight from her and stuff I picked up from my experience overhauling fonts and layout:
So, I made a program to do that! You store a list of students for a given class period in what I called the
roster (just a dictionary of students). Each
Student object keeps track of the number of times it has been selected and its probability of being selected in the next round, as well as whether or not the student is absent.1 It took me a little more than a week to finish, as I was still muddling through Python as I went, and at the end, I had a working final product! A rough one, but a working one! And then I went off on my merry way, doing more and varied projects and slowly building up my Python chops, getting code review, etc. Somewhere along the way, so gradually I didn’t even realize it, I began to feel competent, like with enough time to think and maybe a little Googling, I could Python my way out of most problems that were thrown at me. And so today, back at Hacker School for Alumni Thursday and itching to write some code (because I’ve been up to my neck in web work for the past few weeks), I opted for a blast from the past, and dived into my very first Python project to poke around, refactor, clean up, and chronicle what I found and what I had learned in the past four months. Here are some findings, accomplishments, and reflections.
(If you’re confused, see my previous post on my Markov generator adventures.)
The other thing I got up to today was implementing some sort of (questionable) part-of-speech-based intelligence. The idea was to have a dictionary for parts of speech, in addition to a dictionary of words. Then the work flow would go something like this:
- start with a random seed
- what part of speech should come next? Given the POS’s we already have, pick at random one that might follow it.
- given the words we have, pick a word that might follow of the correct part of speech. If none exists, repeat from step 2.
Now, using word trigrams and POS trigrams, the above process doesn’t really add much beyond what using plain ‘ol word trigrams gets you. Could I make something better, though, by using, say, 4-grams or 5-grams of parts of speech?
Man, I’ve hardly written code in three whole weeks! Such a strange feelings, after 3 solid months of coding. Anyway, back at Hacker School for the day, and with my OPW application in, I’ve been itching to actually write some code, so I revisited my old Markov generator project, which takes a training corpus and generates psuedo-random texts in the style of that corpus.
Having successfully submitted my OPW application, and in the process submitting my first open-source contribution, I have lots of thoughts and feelings.
Part 1: Setting up the environment
Setting up your environment is awful. You think, “how long can it take to set up a virtual machine and install this software?” The answer? Longer than you could ever imagine. Especially if your project is on a platform you’re not familiar with, ask for advice early and often—because inevitably, something will go wrong and you’ll need to ask someone wiser for help anyway, and you might as well not a bunch of junk to undo by the time you do. (Like when I tried to install VirtualBox Guest Additions and it destroyed by VM’s video driver, and in fact all video drivers on any VMs I later installed. I had to wipe VirtualBox and start over. No fun.)
I spent a ton of my time at Hacker School learning how to ask questions (or, to put a finer point on it, learning how to not know things and admit to others that I don’t know things). The main reason that HS was so hard at first was that I wasn’t good at asking questions, at admitting when I didn’t know things, at letting myself (I feared) appear “stupid” in front of others. I was still better than some folks at pushing through this, but I wasn’t as good as I would have liked. (This is all tied into impostor syndrome, of course.)
I got vastly better at this skill as I spent more time at Hacker School. I grew more comfortable in the environment, I gained trust in the folks around me and in my own abilities, and I came to believe that my asking questions, even ones about really basic (quote-unquote-“basic”) things, was a display of intelligence rather than a display of ignorance.
What I didn’t realize about my shiny new skill of “Admitting When I Don’t Know Something and Asking Questions” was how context-dependent it is. At Hacker School, in person or on Zulip, I feel totally comfortable asking questions about “simple” things, and admitting that I’m totally in over my head with, say, troubleshooting my Virtual Machine installation and would someone please help me, and what is actually the difference between GET and POST because I never really learned it… that sort of thing. But as I prepare my application for the coming round of OPW and dive head-first into IRC chats about programs and programming styles I’ve never used before, that all seem to require strange dependencies or have to be run on X virtual machine with Y stuff built on it, I recognize a feeling from my early days of Hacker School.
Doing one thing at a time is very difficult.
Here I am, first Monday without returning to Hacker School, sitting down to say “Okay world, I spent the last three months writing code and it was awesome but I should know something about theory, algorithms, etc.; time to do some studying.” I intended to sit down with Interactive Python and blaze through a section or two before turning away to work on my other projects, job applications, etc.
INSTEAD, I was filled with a sudden anxiety—what if Interactive Python isn’t the right course for me? What if it’s an okay course but there are better ones out there? What if by doing Interactive Python I’m missing the perfect algos course for me and this perfect course and I will be like ships passing in the night, never knowing what we might have had together, and all because I chose to work on Interactive Python.
Today on “Bugs that everyone already knew about but Maia found out about for the first time so will write up anyway”, we’re going to talk about the perils and pitfalls of using mutable objects as default arguments for functions in Python. (This episode brought to you by Maia’s contradance database and the letter Y.)
No, nothing went wrong in my code that caused me to learn this lesson, but multiple code reviewers raised red flags about this line in my code:
def resolve_query_dict(d, moves_list=Move.objects.all()).
Move.objects.all(), by the way, is a fancy Django function that returns a list of all of the
Move objects in your database, and since I would likely never be running this code over an extended period of time while things were added to the database, accidentally freezing the value of “all of the moves in my database” wouldn’t have really been an issue, but the dangers of writing code like the above are still whacky and interesting. Basically, odd things happen when you use mutable objects or called functions as default variables in your functions.
JS != JQuery!!! They’re different things! They each have different sets of methods, and you need to keep track of whether any given thing you’re dealing with in web scripting is a JQuery or DOM (and therefore JS) object.
Alas, it seems that my dreams of writing a choral harmonizer in the style of J.S. Bach have to be put to bed until another day. Susan and I have been taking various stabs at this, trying out a few ineffective Python midi programs (one of these, incidentally, had ZERO documentation and was THE MOST FRUSTRATING THING EVER) before settling on mingus, a midi/music theory Python library. Unfortunately, it seems like no one’s addressed any bug reports since 2011, so when we realized that midi read-in was totally borked, we were a little stymied. Specifically, if we gave it this file as input:
It returned this mess here: