Uma vista de fora

Uma vista de fora - 10 anos de PyLadies São Paulo

Introdução

Olá, tudo bem? Primeiramente fico muito feliz e muito honrada de ser convidada a dar esta palestra hoje. O décimo aniversário é um marco importante para uma comunidade como a de vocês. Mostra que ela é importante para as pessoas, que muitas pessoas a amavam o suficiente para cuidar dela ao longo dos anos.

Também é uma oportunidade para refletir sobre o passado e como chegamos até aqui, bem como para pensar sobre o futuro. Todas nós PyLadies queremos que esta organização continue, cresça e floresça. Mas sabemos bem que a vida acontece. As pessoas vêm e vão, com mudanças em empregos e carreiras, evoluções da tecnologia e todas as coisas de família, saúde, e tudo. Então não é comum que uma comunidade como esta dure dez anos, e continue a partir daí. Em outras palavras, o seu décimo aniversário é uma coisa importante, como dizemos em inglês, "a big deal".

Esta ocasião é importante para mim porque conheço o grupo de PyLadies São Paulo por quase toda a vida dele. No Python Brasil [12] conheci as organizadoras deste novo grupo, PyLadies São Paulo, e me lembro do orgulho e entusiasmo que elas demonstraram. (a propósito, guardei aquela camiseta e a usei até que ela estivesse totalmente gasta.)

No ano seguinte, eu dei uma palestra no segundo aniversário, e depois permaneci conectada com as PyLadies de São Paulo, encontrando-me com elas em conferências em todo o mundo e online durante a pandemia.

Na verdade, fiz tantos amigos e amigas brasileiras que decidi estudar português há alguns anos, e desta vez posso falar com vocês em português. Quando visitei o Brasil em 2016 prometi que da próxima vez poderia falar português. Infelizmente, ainda não pude visitar outra vez e hoje, com o regime anti trans atual no meu país, não me sinto confortável viajando internacionalmente. Mas estou pronta se as coisas mudarem.

Então, tendo visto esta comunidade durante tantos anos, sinto-me quase como uma tia das PyLadies São Paulo, e por isso é muito especial para mim falar com vocês. E espero que a minha visão de fora desta comunidade mostre tanto as ameaças e os desafios que vocês podem enfrentar no futuro quanto as qualidades que fazem este grupo tão especial.

Livros

Antes de começar a palestra, deixe-me mencionar mais algumas coisas. Sou autora do Quick Python Book, agora na quarta edição, e com um prefácio de Luciano Ramalho. Sempre fui grata pelo apoio dos brasileiros, e pedi à minha editora, Manning Publications, alguns códigos para cópias (ebooks) gratuitas do meu livro e um desconto em homenagem ao evento. As organizadoras vão compartilhar/compartilharam os detalhes.

Conexão

Eu disse que fiz muitos amigos nesta comunidade, mas também devo dizer que sempre fico feliz em ter mais. Estou aposentada agora, então não estou tão conectada com o cenário atual de empregos na área de tecnologia, mas se alguém quiser se conectar para conversar sobre outros assuntos, estou aberta a isso, seja em inglês ou português. Além disso, estou mais interessada atualmente em música, arte e leitura. Acabei de terminar uma aula sobre música brasileira com um cara no Rio, e posso dizer que descobri o Veríssimo pelo menos alguns meses antes da sua morte recente. Então, se você quiser conversar sobre essas áreas, ficarei feliz em fazê-lo. Você pode me encontrar no LinkedIn, Facebook, Bluesky ou no meu site.

Sobre a palestra

A última coisa é falar um pouco sobre esta palestra. Primeiro não vou usar slides. Não gosto deles, porque na minha opinião elas destroem ativamente a inteligência. Sim, mostrarei algumas imagens no fundo, mas a coisa mais importante será minha voz. Se vocês quiserem ler as palavras, devido ao meu sotaque ou o que seja, o texto está em naomiceder.tech/blog.

Além disso, tenho que admitir que a primeira parte da palestra contém coisas sombrias. Aqui às vezes dizemos que existe uma antiga maldição chinesa que diz "Que você viva em tempos interessantes." Na verdade, não existe nenhuma evidência de que seja chinesa, nem antiga, mas sim, sem dúvida é uma maldição, e também uma descrição justa da nossa situação.

Então vou começar com todos os problemas que enfrentamos, mas prometo que o final será otimista.

Por fim, não vou falar muito de temas técnicos. Suponho que, estando aposentada, eu tenha o luxo de pensar mais na humanidade, a arte, a música, etc. e eu diria que no geral assuntos técnicos são detalhes de implementação que nos dizem pouco sobre as coisas mais importantes. Para usar o lema que aprendi aqui no Brasil há 9 anos, "Pessoas > tecnologia."

Desafios e ameaças

Então

Duas semanas atrás eu vi a palestra que dei no segundo aniversário. Não gosto muito de ver os meus vídeos antigos. Sim, gostei do meu cabelo (menos grisalho) e dos meus óculos. E gostaria de ter 8 anos menos, claro.

Na verdade, agora essa época parece um mundo diferente. O vídeo me lembrou de como as coisas eram quando PyLadies SP começou (e tantos outros grupos de PyLadies). Acreditávamos que iríamos mudar e melhorar o mundo com tecnologia, que a inclusão continuaria a crescer, e a única coisa que deveríamos fazer seria ensinar mais mulheres e pessoas marginalizadas as maravilhas do Python e da tecnologia.

Ser mulher, ou LGBTQI+, ou uma pessoa não branca parecia ter menos desvantagens, com a esperança que as coisas fossem ainda mais favoráveis no futuro.

Alunos dos bootcamps conseguiam bons empregos e carreiras boas, e as grandes empresas sempre precisavam de mais pessoas, e ofereciam benefícios generosos, como comida, transporte, serviços e até mesas de pebolim e pingue-pongue. (Eu nunca entendi isso) Os salários eram ótimos, e as oportunidades estavam por toda parte, e se não encontrasse um emprego no próprio país, seria fácil migrar para fora.

Havia problemas, sim. Havia homens sexistas e machistas, que muitas vezes não aceitavam mulheres e outras minorias. Mas a opinião geral era a nosso favor. A mudança climática era uma preocupação, a ultra-direita estava surgindo em vários países, mas tudo estava (ou parecia) sob controle. Ou assim acreditávamos.

Agora

Nos oito anos seguintes, como dizemos, a vida aconteceu. Os partidos da direita ganharam mais poder, e cuidar das pessoas tornou-se um pouco menos importante.

Com a chegada da pandemia, tudo mudou. Ficamos isolados, trabalhando remotamente, lutando para manter um sentido de conexão e comunidade por meio de ligações com amigos, eventos no zoom, etc. Algumas pessoas morreram, outras lutaram contra a Covid longa, todos sentíamos mais sozinhos. Conferências e meetups pararam ou até morreram.

Finalmente, superamos a pandemia. As coisas reabriram e recomeçaram, mas não era o mesmo de antes. Eu diria que a pandemia marcou a transição para uma nova era em que estamos agora. O mundo de hoje é mais sério e menos gentil. Esta é a era do "hard tech". As empresas não se importam mais nem com empregados, nem com consumidores, as startups não estão mais tentando mudar o mundo.

Menos consideração

Elas agora estão focadas em conquistar clientes maiores e mais poderosos, grandes corporações e governos. As forças armadas e as finanças agora são preferidas. Lucros e dados concretos são preferíveis a mudar o mundo, e considerações éticas são menos importantes. Lembramos quando o lema do Google era "Não seja mau"?

Agora há menos consideração pelos funcionários e vemos um movimento universal de "volta ao escritório" "Back to the office" e uma redução de benefícios do escritório. Também estamos vendo demissões. As empresas não estão dispostas a contratar pessoas formadas em bootcamps e preferem oferecer contratos temporários em vez de vagas permanentes.

E mesmo lucrando com open source software, essas empresas fornecem pouco suporte às comunidades que o produzem. A PSF teve que parar de subsidiar eventos e conferências devido à falta de recursos, apesar do fato que Python é atualmente a linguagem mais popular do mundo e vital para a IA e a ciência de dados, que estão gerando riqueza. Sem mais apoio financeiro, as conferências e meetups serão impossíveis, o que será prejudicial ao software do qual dependem, mas elas parecem não perceber nem se importar.

Movimentos da direita

Ao mesmo tempo, movimentos de direita estão crescendo e governos antidemocráticos estão se tornando mais comuns. O resultado é que as empresas estão abandonando a diversidade e a inclusão e elas se tornaram um alvo político da direita. Sim, isso é mais óbvio com o governo de Trump, mas a influência dos EUA é amplamente sentida em muitos países. E a atitude anti diversidade permite que homens insultem mulheres e minorias, e torna mais difícil para pessoas não homens brancos conseguirem empregos e mantê-los.

Esse movimento já está reduzindo oportunidades, com mais restrições à imigração e até mesmo (no caso dos EUA) tarifas, que são prejudiciais a todos.

As guerras

E claro, agora temos guerras, na Ucrânia, em Gaza, na África, e ameaças de ainda mais guerras ao redor do mundo. Membros da comunidade Python de todos os lugares foram afetados, e para ser sincera, parece que a situação está piorando.

Todos esses fatores estão nos separando e nos enfraquecendo no exato momento em que precisamos trabalhar juntos.

A IA

Além disso, agora vemos que a IA parece estar dominando o mundo, uma força imparável. Sim, às vezes a IA faz coisas impressionantes, mas muitas vezes também cria problemas igualmente impressionantes. A IA tomou e usou a propriedade intelectual de muitos milhares de autores (inclusive eu) sem permissão e sem recompensa.

A IA também consome recursos a uma taxa incrível. Aqui na região de Chicago, as contas de energia estão disparando porque não temos energia suficiente para abastecer os parques de servidores do LLM e atender às necessidades das pessoas.

A IA também consome água potável e produz CO₂. O Google afirma que um prompt de texto "normal" consome uma pequena quantidade de energia e água e produz pouco CO₂. Parece, no entanto, que eles não estão incluindo os custos de todo o processo e infraestrutura. E, claro, nem todos os prompts são simples prompts de texto. Só podemos imaginar quantos recursos a mais são consumidos para produzir vídeos bizarros, imagens no estilo do Studio Ghibli e imagens de pessoas com 14 dedos. E agora, cada consulta de pesquisa do Google envolve IA, então mesmo pequenas quantidades de consumo precisam ser multiplicadas por bilhões todos os dias.

Outra consequência da IA será que os líderes empresariais acreditam que não precisam de desenvolvedores, especialmente os juniores. Já que a vibe coding supostamente pode fazer o mesmo trabalho, por que gastariam dinheiro (e tempo) contratando juniores? Agora, até mesmo graduados de universidades de prestígio estão com dificuldades para encontrar emprego, e os formados em bootcamps não têm chance.

É claro que isso não funcionará a médio ou longo prazo, nem para empresas nem para indivíduos. Mesmo que a IA pudesse substituir alguns programadores (e isso é verdade em pouquíssimos casos, na minha opinião), o que as empresas farão no futuro, quando não houver desenvolvedores de nível médio ou sênior, já que eles não foram contratados como juniores?

Há também preocupações com os efeitos da IA nos mercados. No momento, as avaliações estão altíssimas, em parte devido ao entusiasmo pela IA e à expectativa de que ela trará um crescimento incrível. Mas o que acontece se o crescimento não for tão incrível? Li recentemente um estudo que constatou que os ganhos de produtividade com a IA são, na verdade, bem pequenos, cerca de 3%. Se o milagre não acontecer, se (como acredito ser o cenário provável) os resultados da IA forem apenas positivos, mas não milagrosos, é provável que assistamos a uma quebra do mercado global, com consequências graves para todos.

O entorno

O maior horror que enfrentamos são as mudanças climáticas. Sem dúvida, as temperaturas globais estão subindo, de forma mais rápida e drástica a cada dia. Em todos os lugares, vemos ondas de calor, inundações, tempestades, incêndios florestais, chuvas torrenciais e muito mais. Ao mesmo tempo, o nível do mar está subindo e os sistemas climáticos estão mudando.

A maioria das pessoas e governos vê isso como uma emergência (o atual regime americano, infelizmente, não), mas ainda não estamos fazendo o suficiente para lidar com isso.

O que fazer?

Stockton

Por que estou contando isso? Não quero que todos fiquem tristes e deprimidas, mesmo que pareçam assim. Um fator na capacidade de sobreviver e superar momentos difíceis é reconhecer as dificuldades sem ceder. Isso se chama "efeito Stockton", em homenagem ao General Stockton, que foi capturado no Vietnã e sofreu torturas brutais. Apesar da tortura, ele se manteve firme e nunca desistiu, e finalmente conseguiu voltar para casa.

Mais tarde, Stockton disse ter notado (e vários estudos confirmaram isso) que homens otimistas irrealisticamente (que sempre diziam: "As coisas vão melhorar em breve, estaremos em casa antes do Natal", coisas do tipo) eram os primeiros a morrer. Como as coisas não melhoraram em breve, eles não voltavam para casa antes do Natal, e a decepção os enfraquecia e, por fim, os destruía.

No entanto, aqueles que reconheceram o quão ruins as coisas estavam e continuavam determinados a perseverar e tentar na esperança de superá-las algum dia foram os que tiveram mais probabilidade de sobreviver.

É por isso que estou lembrando vocês de todos os desafios e ameaças que enfrentamos. Mas a segunda parte também é importante: precisamos ter esse tipo de otimismo teimoso, informadas sobre os desafios, mas ainda determinadas a fazer o que pudermos para um dia superá-los.

Este tipo de otimismo é um ato revolucionário. Ou seja, como disse Noam Chomsky, "otimismo é uma estratégia para criar um futuro melhor. Porque, a menos que você acredite que o futuro pode ser melhor, é improvável que você assuma a responsabilidade de criá-lo."

Por que otimismo?

Por mais importante que seja enxergar os desafios com clareza, é igualmente vital considerar honestamente nossas razões para otimismo. Um fator vital para enfrentar todos os desafios que mencionei está ao nosso alcance. É a força unida de todos nós, a força da comunidade. E aqui, nesta comunidade, vejo três fortes fontes desse espírito de comunidade.

Python

Primeiro, a comunidade está no DNA de Python. A comunidade sempre foi uma parte importante de Python, o que uniu tantas pessoas com tantos interesses diferentes. Se você ainda não viu o documentário recente sobre Python, recomendo fortemente. Como disse Bret Cannon (um ditado que já peguei emprestado muitas vezes): "Vim pela linguagem, fiquei pela comunidade". E todos nós fazemos parte dessa tradição.

É o que manteve o progresso da linguagem durante várias crises. Em 2008-2009 a crise financeira levou a grandes perdas da PyCon US. Tivemos contratados hotéis, espaços de eventos e, como aconteceu, as empresas não tinham condições de enviar pessoas para a conferência. Pareceu possível que a PSF não poderia continuar. Mas como comunidade perseveramos e superamos.

Eu sei isso por experiência própria. Quando estava fazendo minha transição, tinha medo de perder minha conexão com a comunidade Python. Pensei que ninguém (ou poucos) me aceitaria, que eu ficaria sozinha. Na verdade, todos se esforçaram para garantir que eu me sentisse aceita. Sim, as coisas não eram perfeitas, mas no geral recebi abraços e apoio.

PyLadies

O segundo fator positivo é a tradição de PyLadies. PyLadies sempre fomentou um sentido de comunidade e apoio mútuo. Desde o início o objetivo foi que nós, mulheres, nos apoiássemos e nos ajudássemos a enfrentar os desafios de ser mulheres entrando em um mundo dominado por homens.

As primeiras organizadoras de PyLadies, Lynn, Esther, e Sophia me fizeram sentir bem-vinda, e, quando estava organizando os primeiros eventos de Trans*Code, elas foram minhas maiores apoiadoras e conselheiras.

Desde o início é uma tradição no almoço de PyLadies em PyCon e EuroPython incentivar as pessoas a compartilhar suas conquistas e serem celebradas. E espero não precisar lembrar vocês que o Brasil tem um dos movimentos de PyLadies mais fortes do mundo inteiro.

Mais importante ainda, PyLadies é uma organização de mulheres, mulheres dispostas a se unir e fazer o que precisa ser feito. E, na minha opinião, essa é uma das forças mais poderosas do mundo.

Cultura brasileira

A terceira fonte da unidade e comunidade que eu vejo talvez possa parecer estranha para vocês. Mas, como estrangeira, é bem claro para mim. É a cultura brasileira.

Sim, eu sei que toda cultura tem suas desvantagens, que nem todas as pessoas de um país, especialmente um país grande como o Brasil, compartilham os mesmos valores e normas. No entanto, acho que há algo especialmente propício à comunidade em vocês.

Viajei literalmente o mundo e conheci milhares de pessoas de diversas culturas. É claro que existem boas pessoas em todos os lugares. Mesmo assim, desde o primeiro dia em que cheguei ao Brasil, nove anos atrás, continuei a me sentir bem-vinda, formar conexões e encontrar amizades duradouras com brasileiros. Nenhuma outra nação me recebeu tão calorosamente. Vocês criaram meu lema favorito - Pessoas > tecnologia. (Outra camiseta que adorei e guardei até ficar gasta).

Não estou exagerando quando digo que agora tenho mais (ou quase) amigos brasileiros do que norte-americanos. São muitos para mencionar, mas quero contar um exemplo só. Quando a PSF me entregou o Prêmio por Serviço Distinto em PyCon em Salt Lake City, em 2023, a pessoa mais orgulhosa da plateia, a que me abraçou mais forte, não foi de Chicago, não foi dos EUA, nem da Europa. Foi um brasileiro, meu amigo Felipe de Morais. Nunca vou me esquecer disso.

Não sei por que vocês se importam tanto com os sentimentos dos outros... Não sei, mas acho importante que você ouça de uma estrangeira que eu nunca encontrei um senso de comunidade tão forte quanto entre vocês. Não é uma fraqueza, é um superpoder, e tenho certeza de que ajudará esta comunidade, não importa os desafios que o futuro traga.

Conclusão

Então, como eu disse no início, vivemos em tempos interessantes... Isso me lembra de uma citação de O Senhor dos Anéis:

"Gostaria que isso não tivesse acontecido na minha época", disse Frodo.

"Eu também", disse Gandalf, "e todos os que vivem para ver tempos assim. Mas isso não cabe a eles decidir. Tudo o que temos que decidir é o que fazer com o tempo que nos é dado."

Eu sei que todas vocês nesta comunidade, assim como todos nós nas comunidades globais PyLadies e Python, temos a tradição de nos unirmos não apenas para sobreviver, mas para superar estes tempos interessantes.

DIY Ear training with Python and Music21, part 2

DIY Ear training with Python and Music21, part 2

Having a basic ear training app (as described in part 1 working, I started to use it. As I mentioned in my last post I quickly discovered I was surprisingly bad at it, and my bare bones app was not helping me as much as I thought it could.

Correcting and learning from mistakes

Not having had much experience with recognizing intervals, I decided to keep things simple and start with just 3 intervals, the major third, the perfect fifth, and a perfect octave. Since I was making plenty of mistakes, I started thinking about how to correct those mistakes. For a while I tried repeating an interval until I got it right, but considering the limited choices (major third, perfect fifth, and octave) and the fact that I was showing the right answer after the fact, that wasn't much help.

I was also finding that I was struggling most with telling a perfect fifth and an octave apart. I have no idea if this is a common issue, but it seemed to me that they are both similarly consonant, and unless I was careful (and all too often even if I was careful) they sounded similar to me.

My approach was first, reduce the possible choices to just those two. I could always add thirds back in later, but first I wanted to get past the fifth/octave confusion. Next I tried creating a cell that picked notes at random and then played the possible intervals. Warming up with this approach seemed to improve performance at least for a session immediately after that.

That said, I do wonder if that approach might be worth trying. but only playing the samples randomly, only part of the time, and progressively less often. Another option might be to play only one reference tone, say the octave or fifth, to help set the stage.

That said, I do wonder if that approach might be worth trying but only playing the samples randomly only part of the time, and progressively less often, might be worth investigating. Another option might be to play only one reference tone, say the octave of fifth, to help set the stage.

Finally, I decided to add code to review the mistakes. Since I was already collecting the incorrect answers, along with the notes and correct interval, it was easy enough to instead add a review of wrong answers after the main run was finished. This randomly selected items from the list of incorrect answers, only removing them when they were answered correctly. After trying it a time or two, I decided to double the list of incorrect choices (incorrect = incorrect * 2), just to give me extra practice with the trouble spots.

Improving feedback

In addition to handling the errors, I had found the feedback was not clear enough. If I made and error, I wanted it to be a little bit obnoxious about it. (As you might guess I'm not totally against negative feedback).

I decided that playing an irritating noise might be a good way to handle indicate an incorrect guess. I wasn't able to get the Jupyter Audio component to play a sound automatically during a loop (although it would as the main code in a cell), so instead I went with the playback3 library and a gong .wav file I found in a quick search. This, along with some clearer messages and a count of the total attempts in a session, gave me much better feedback.

The current code

The actual code was this:

choice = ""
correct = []
incorrect = []
total_tries = 0
while choice.lower() != 'q':
    total_tries += 1
    test_interval = random.choice(intervals)
    base_note_name = random.choice(chromatic_guitar[:-12])
    base_note = note.Note(base_note_name)

    test_stream = stream.Stream([base_note, 
                     base_note.transpose(test_interval)])

    test_stream.show("midi")
    choice = input("interval: ")
    clear_output()
    if choice == test_interval:
        correct.append(choice)
        print(f"{choice} is correct\n")

    elif choice.lower() == 'q':
        total_tries -= 1
        break
    else:
        playsound("gong.wav")
        incorrect.append((test_interval, base_note, choice, base_note.transpose(test_interval)))
        print(f"{choice} is incorrect\n")

    print(f"{len(correct)}/{len(correct)+len(incorrect)}")
    print(f"{base_note.name},  {base_note.transpose(test_interval).name} --> {test_interval}, {choice}")

incorrect = incorrect *2
while incorrect:
    total_tries += 1
    print(f"Reviewing {len(incorrect)} missed items")
    test_item = random.choice(incorrect)
    test_stream = stream.Stream([
                                      test_item[1], 
                                      test_item[3],
                                ]
                               )
    test_stream.show("midi")
    choice = input("interval: ")
    clear_output()
    if choice == test_item[0]:
        correct.append(choice)
        incorrect.remove(test_item)
        print(f"{choice} is correct\n")
    elif choice.lower() == 'q':
        total_tries -= 1
        break
    else:
        playsound("gong.wav")
        print(f"{choice} is incorrect\n")
    print(f"{len(correct)}/{len(correct)+len(incorrect)}")
    print(f"{test_item[1].name},  {test_item[3].name} --> {test_item[0]}, {choice}")

percentage = float(len(correct)/total_tries * 100.0 if total_tries else 0)
print(f"{total_tries} tries for {len(correct) } intervals correct = {percentage:02.1f}%\n")

if not incorrect:
    print("All errors fixed")
else:
    print(f"{len(incorrect)} errors not fixed")

Future options

This is still pretty simple minded. There is no attempt to track results or progress over time and no analysis of the types of errors which could shape remedial exercises. Both of those would require adding a SQLite database, which would be easy enough to do.

Beyond that, with a database, I could also add spaced repetition to the sessions, refreshing old work why moving on to new items. I had included that in my first notes on the project, but I'm not sure if I'll feel the need to implement it. If I do, I guess that would lead to a part 3 of the series.

Results

But even with it still being simple, I now had\ something that was starting to work as I'd hoped. I can fire up this notebook every day, work through 3 or 4 runs of 30 choices and get extra practice with my mistakes.

I've been pretty consistent in practicing every day, which I think is at least partly due to the fact that it's my code and I had to understand the problem in order to create it.

So far I've been happy with the results. After a few days of practice, I can now more reliably tell my fifths from my octaves, I've even added both major and minor thirds back in, and am surprised at how much easier those are for me.

If you want to leave a comment, or just prefer a more interactive experience, this post can also be found on Sustack at https://naomiceder.substack.com/p/diy-ear-training-with-python-and-2d5

DIY Ear training with Python and Music21

DIY Ear training with Python and Music21, part 1

For the past 3 years I've been studying classical (and now also jazz) guitar, music theory, and doing a little composing. I tend to dive into things, and in that time I would say that I've made it to intermediate level as a classical guitarist, I've learned a fair bit of music theory, and I've written a few pieces for guitar.

One piece has been missing, however. That is ear training. I hear and learn melodies and rhythms just fine, but I've been missing the ability to recognize intervals by ear. Is that a perfect 5th? Or is it a minor 3rd? Maybe an octave? My guesses were not nearly as reliable as I thought they should be.

The answer, of course, is ear training, basically practicing identifying intervals until one's recognition improves. There are, of course, tons of apps and web sites that will help you do that for free.

That would be the easy way, or at least the obvious way. But I've tried them (very briefly) before and they never engaged me. In fact, they just seemed frustrating. After decades of teaching, I know that frustrating = un-motivating = doomed to fail.

So my solution was to create my own ear training program. The process is inherently more interesting (at least for me). You have to think a bit about how to go about the training, you have to think about the structure of a program to do that, and you have to write the code. And you have to TEST the code, which in itself assures more time using it.

I should also note that so far, this entire project has been free from AI. Yes, I know I could get a chatbot to generate the code, the approach, the design, or even a whole ear training website. If I were mainly interested in using AI to generate code, then maybe that would make sense. But again, that would diminish, or even eliminate, my involvement and motivation in the whole process. In the end, it would be no better, if not worse, than just using one of the many pre-existing apps.

So here begins my ear training journey, coded the old fashioned way.

Basic app idea

The basic idea is just play intervals, try to guess them, and evaluate whether the guess is right or wrong. So that means that the pseudocode at a high level might be something like:

loop:
    Get a note name at random from list of notes
    Get an interval name at random from list of intervals
    Create first note from note name
    Create second note of interval by transposing the  first note by the interval
    Play the notes 
    Get the user's response
    Check response against actual interval name

The implementation of that basic idea was the next step.

Platform

I was pretty clear from the beginning that I would use a Jupyter notebook for this experiment, since I had no need for a standalone app, and the convenience of a notebook is hard to beat. For generating the sounds, Music21 seemed right for me, since it can generate midi sounds and can manipulate and transpose notes, making it easy to create pairs of sounds separated by arbitrary intervals.

I knew I needed to install music21 so once I had a notebook ready (I used pyenv to create a Python 3.13 environment for the project), I installed music21 from within my notebook:

%pip install music21

The code, first iteration

The first thing I needed to do was load dependencies:

from music21 import * # import everything from music21

import random

from IPython.display import Audio # load the Jupyter audio widget
from IPython.display import clear_output # used to clear the cell after an attempt

I needed music21 of course, the random library for selecitng notes and intervals, and from the IPython.display library I would need both the audio player and the clear_output function to clear the output after each guess.

Since I'm primarily a guitarist, I wanted to use the range of sounds available on the guitar. I had already experimented with music21 a couple of years ago, so I had the code to define the notes of the fretboard ready to go:

chromatic_guitar = ["E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3", 
           "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4",
           "C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5",
           "C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6"
                  ]

Transposing is pretty easy to do with music21, you can either use a number of steps or a string with an interval name (in either case, the default is to transpose up, and prepending a "-" will transpose down.) For example:

from music21.note import Note

Note("E").transpose(1)    # E to F
Note("E").transpose(-1)    # E to Eb
Note("E").transpose("m3")    # E to G

Using a list of interval names is more useful for the current purpose than using integers so I created a list of intervals, but commented out all but the perfect 5th and perfect octave to make it a bit easier on my untrained ears:

intervals = [
    # "m2",    #minor 2nd
    # "M2",    #major 2nd
    # "m3",    #minor 3rd
    # "M3",    #major 3rd
    # "P4",    #perfect 4th
    # "D5",    #aug 4th/dim 5th
    "P5",    #perfect 5th 
    # "m6",    #minor 6th 
    # "M6",    #major 6th
    # "m7",    #minor 7th 
    # "M7",    #major 7th 
    "P8",    #perfect octave

After those three cells of preliminaries, the basic app looked like this:

Disclaimer: of course my actual first iteration was messier than this, I've cleaned up the false starts, errors, and extraneous bits.

# initialize
choice = ""
correct = []
incorrect = []

# loop
while choice.lower() != "q":
    test_interval = random.choice(intervals)
    base_note_name = random.choice(chromatic_guitar[:-12])
    base_note = note.Note(base_note_name)
    test_stream = stream.Stream([base_note, base_note.transpose(test_interval)])

    test_stream.show("midi", autoplay=True)
    choice = input("interval: ")
    clear_output()
    if choice == test_interval:
        correct.append(choice)

    elif choice.lower() == "q":
        break
    else:
        incorrect.append(
            (test_interval, base_note, choice, base_note.transpose(test_interval))
        )

    print(f"{len(correct)}/{len(correct)+len(incorrect)}")
    print(
        f"{base_note.name},  {base_note.transpose(test_interval).name} --> {test_interval}, {choice}"
    )

Reflection

This was enough to get me started, and I soon discovered that I was every bit as bad at telling perfect fifths and octaves apart as I'd feared, and I struggled to call 2/3 of the pairs correctly.

That pushed me back into teacher mode, and I started thinking about how I could modify the code to help me learn. As I thought about it, there were several things that were not optimal.

First of all, the feed back on whether a guess was right or wrong, was only indicated by the change in the counter of correct over total attempts. More obvious and forceful feedback would be helpful,

Secondly, there was no way to learn from the mistakes, other than displaying the incorrect list. In fact, I'd decided to use lists for correct and incorrect, rather than just counters, because I was pretty sure I'd want to do something to help learn from the mistakes.

I'll talk about what I did to address these issues (and why) in the next post, coming soon.

If you want to leave a comment, or just prefer a more interactive experience, this post can also be found on Sustack at https://naomiceder.substack.com/p/diy-ear-training-with-python-and

Thoughts on Chelsea Manning's README.txt

A surreal nightmare - Chelsea Manning's README.txt

Here are my thoughts on Chelsea Manning's memoir README.txt

Reading Chelsea Manning's README.txt was an odd experience for me. On the one hand, there were lots of things that made me feel connected to her and interested in her story. The most obvious was that we are both trans women, and we began our transitions at roughly the same time. And of course, her struggles for trans care were widely publicized, so I was aware of them, and to a certain extent my transition was also fairly public, if within a much smaller social network and the Python community. We had grown up in very conservative parts of the country - in her case, Oklahoma (at least in part) and in mine, Nebraska. In addition, her use of technology and the internet was similar to mine in the 90's and 2000's.

With that said, there were some real differences. For one thing I'm more than 30 years older, so I had served a self-imposed term of decades of suppressing my gender identity, waiting until circumstances made it safer and easier to transition. Chelsea's childhood was abusive in many ways, while I would not claim that of mine. And in spite of some temptation, I had resisted and avoided entering the military.

In spite of the points of connection, I was not immediately grabbed by her story. She starts with the striking scene of her desperately trying to upload all of the files via a shaky network connection in suburban mall land, during a snowstorm no less, with less than 24 hours before she has to get on a plane back to Iraq. But the telling of it is a bit pedestrian, and it takes a while for the story to emerge. Dramatic as it might be, the how and the why of the uploading of information about the war is not the story. Rather it's what happened after she was caught that I found more compelling.

The story of how she came to have that information and how she uploaded it is all too simple, and the why is not so well articulated, emerging as it does from a tough childhood and rootless adolescence that ended in the army almost out of desperation.

But once she is discovered and taken into custody things get much more gripping. The style is still matter of fact, flat, and mostly emotionless, as if it could only be told by keeping it safely at arm's length. It's a story that is almost Kafka-esque in its absurd cruelty. Earlier, when describing basic training, Chelsea acknowledges that its function is to break people, tear down part of who they are in order to reconstruct them as different people. It's interesting to me that of all the veterans I've known, the only other person who described military training that way was another trans woman, who washed out of ROTC because she wouldn't endure that.

Chelsea on the other hand gives a sense that the process of breaking and rebuilding that happens basic training was not all bad for her. So it's interesting that once in the clutches of the US government she is the target of a similar process, except there is no goal of rebuilding a new personality this time. This time the only goal is to destroy her totally. The unemotional descriptions of the inhuman torture they put her through leaves no doubt that the primary concern of her jailers and the government was pure revenge, nothing more.

That she survived her initial captivity and what was a bizarre show trial (bizarre in that many parts of it were blacked out in the name of "security") and her early captivity is amazing. The treatment she received from her own government, our government, as a citizen on US soil, under an administration that was supposedly humane and progressive, should be a curative for any idealism in regards to the justice of our ways.

If there is anything positive in the story it would be that once she given even the slightest breathing space, she was able to find people to help her as she found ways to deal with the government and even gain concessions from it, both in terms of dealing with prison and in forcing the grudging accommodation of her gender transition.

In the end her eventual movement to Leavenworth to serve her 35 year sentence (which seems almost like summer camp in comparison to what went before) and even the eventual commutation of her sentence and her release all seem not so much the restoration of justice as a calculated attempt to evade the judgment of history.

Chelsea emerges as someone of intelligence, of stunning courage, but not unscathed. After a difficult youth and her nightmarish captivity, she is not broken, but the scars (and even the still open wounds) are extensive, and one wonders if Chelsea Manning will ever be at peace in this world. And to be honest, one wonders if her ordeal was worth it.

Cómo crear y cuidar una comunidad

PyCon Bolivia 2022 Keynote

Esta charla se presentó como keynote de PyCon Bolivia 2022, 2022-12-09

El texto y las diapositivas de esta charla están aquí.

A Time of Gifts

A Time of Gifts

Delivered as the closing keynote of PyCon 2022, Salt Lake City, Utah, 2022-05-01

Versions in Spanish and Portuguese were given at PyCon Latam 2022, 2022-08-27

I don't usually post the text of talks I've given, but I thought I'd make an exception for this one. This started out as a love letter to the Python community, but ended up with a bit of what I suppose you could call parental concern.

Good afternoon. I am honored and delighted to be here. Before I say anything else I'd like to note that this is our 20th PyCon, yes, this is number 20, and my 20th PyCon as well, and I like to give my deepest thanks to the organizers, the staff, the volunteers, and of course to all of you, for making it such a joyful return to the world. Thank you all.

I've called this "A Time of Gifts," which is inspired by a little gem of a travel memoir by Patrick Leigh Fermor, who in the early 1930's, after being thrown out of his last year of British public school for not taking it seriously enough, decided to walk from the Netherlands up the Rhine, across Europe, down the Danube and ultimately to Istanbul.1

It took him a couple of years, and the focus of the book is not so much the places and sights he visited, nor the historic events unfolding around him (he crossed Germany and Austria as the Nazis were coming to power, but seems to hardly notice). Rather Fermor is interested in the people he met along the way - boatmen and truck drivers, farmers and shopkeepers, even an occasional aristocrat, whose gifts of food, shelter, and companionship helped sustain him along the way.

For me, and maybe for many of you, my time in this community has been my time of gifts, gifts that have sustained me in many ways on my journey over the past 20 years to various continents, across two genders, through different stages of my life. So that led me to think about how we value and share the gifts of our community and how people have compared open source communities like the Python community to a gift economy.

Here at PyCon I overheard someone say, "In Python people know how open source works." Maybe. But I wonder if that understanding is really the same for everyone. There are a lot of ways to look at communities, and I expect that there will be various different opinions. But I do think it's important for communities to think about and articulate their principles, and I want to present a way of thinking about our community that makes sense to me. Maybe at least it will start some discussion.

I want to be clear that what I'm about to say is purely my own opinion - I stepped away from the PSF board nearly 2 years ago, so please don't blame any of them.

I would argue that, as a community organized around an open source language and ecosystem, we have a gift orientation. The thumbnail definition of this orientation is that people contribute what they can when they can, and in turn share the resources and help contributed by others in the community.2

This style of gift giving or mutual contribution is what we see in our Python communities - some people are contributing code, others documentation, still others the labor to hold community events. All of these gifts are freely given and everyone enjoys the benefits. Right? Sort of like a utopian anarcho-syndicalist commune, or like what the animals had on Animal Farm until the pigs turned into totalitarian dictators.

And I think for many of us who love this community, this is the narrative we turn to, particularly in misty nostalgic moments, which at least old-timers like me experience at every PyCon. But in those moments we tend to forget that things are never quite that simple, that perfect, or that idyllic. As Python, our community, our projects, and our gatherings have grown, things are not so clear. In fact, a lot of people are questioning whether this model of open source powered by gifts is still sustainable.

I suppose part of the problem is that the open source world in general and Python in particular have been almost too successful. Even as we've grown in every aspect, the number of users and their demands has grown exponentially faster. How can such relatively tiny groups of volunteers keep a community and a language used by millions going?

It's easy to find examples of things that go wrong. One issue is burnout on the part of the volunteers who make it work. Many times I've seen what I call "shooting stars", people who burst onto the scene and start contributing to the community, often in multiple ways, showing superhuman amounts of energy and enthusiasm. It seems that only months after their first events, they are organizing other events, teaching courses, contributing code, and more. These newcomers are so successful, so eager to help, that we, as a community, happily give them more and more to do, to the point that old timers like me start wondering, "how can anyone possibly do all of that?"

The answer usually is that they can't, at least not for very long. In those cases, we'll start to notice that they're looking tired, that the enthusiasm is fading even as the workload continues to go up. I've had them take me aside and quietly ask me how to deal with the stress, how to keep all the balls in the air… and when I tell them that the answer is to do less, they never seem to accept it. Oh, you can tell that they'd love to, but by now they don't have time. They have an event to organize, a review or blog post to edit, code to write, planning calls to join.

And after a few months, or a couple of years, maybe, they fade away. Emails go unanswered, deadlines slip, pull requests are ignored, calls are missed, and so on. The demands of all that they were doing, for free, as volunteers, combined with demands of work, the needs of family, etc, have literally sucked all of the energy out of them. The tank is empty and they have no more to give, and the relationship between them and the community is damaged, often irreparably.

I've also seen people who've started slower, and built on their work over the years until they have become key developers, or maintainers, or key community organizers. They've been doing what they do for many years now, usually getting more complaints than praise, and they feel that their work is being taken for granted. In many cases I think they have too much invested emotionally to walk away, but they're tired, and they're wondering how much longer they can hold on.

Sometimes those leaders have given so much more than anyone else that they end up running the project alone. They hold all the credentials, and whenever something needs to be done, everything goes through them. When encouraged to share the load, they tend to explain that they can handle it just fine, and, besides, it's more work to train new people than it is to do the work. Or maybe they feel that they just don't have the knowledge or the time to onboard new people.

On the other side are the people who are eager to join a coding project or community effort and to help out, but who end up being turned away. I've often see people whose sincere, even eager, offers of help end up ignored for a variety of reasons: no one has time to onboard them, the project that they're interested in has enough people involved (they think), they happen to be asking in the wrong place, they're trying to come in at too advanced a level, or any number of things.

If they are trying to do something that they aren't ready for yet, they can be directed towards more appropriate contributions. But often it seems to me that they just fall through the cracks. And in those cases each time they try to get involved and somehow get turned away they are less likely to try again, and we end up losing them.

The end result is that our projects and our community initiatives are at risk of dying as people burn out and are not replaced. So it happens that we often find open source projects abandoned, with unanswered issues, ignored PR's, and out of date dependencies… or initiatives with silent mailing lists, ghost town slacks, and so on. Occasionally one might get revived, but most are simply left behind.

Some even see this as just the way that open source projects work. I was reading an article about the sustainability of open source a couple of weeks ago and a developer/maintainer of several JavaScript projects characterized open source as "a model that relies on people giving more than they can for very little or nothing in return, and hoping that there will be someone to take over the mantle when the previous person burns out."3

That description of how open source works tells me that if we are in fact a gift giving culture (and I believe we are) things are going wrong. We have people giving more than they can sustain and others who are able (barely) to sustain what they give, but feel that they aren't receiving anything in return. I'm sure that feeling is made even worse by seeing companies use their work in place of systems that used to cost hundreds of thousands of dollars, without acknowledgement, and certainly without giving back even a tiny fraction of the money that they are now saving.

And then there are others who feel that their gifts are being rejected. This last is also serious - in a gift giving culture refusing someone's gift is an insult, it's a way of saying you don't want them in the community. So it's no wonder sometimes we struggle to find new people to take over projects.

So clearly there are challenges we face as an open source community. The question is what do we do about it? What can we do? To my mind the first step is to understand what's going on and what motivations and values are driving people's behavior.

The way you think about something, the narrative you tell yourself, has an impact on how you deal with it, and some ways of thinking about a problem can actually keep you from fixing it. I know from personal experience that sometimes changing, or at least clarifying, your narrative can be an important first step in dealing with a situation better.

So what does drive communities like ours? Why are we here at a conference like this where there is so much talk about community? 20 years ago the most popular explanation, popularized in things like The Cathedral and the Bazaar, was that open source was driven by self interest. Enlightened self interest to a degree, since in practical terms you were more likely to get what you wanted if you were agreeable, but still just self interest. People worked only on what interested them or benefited them, and beyond that the only other motivation was the ego boost you could get from reflecting that you were the one to solve the problem, and everyone interested in the project would know it. In fact even if you were to do something nice, something altruistic, without that ego boost as payback, that was only because you could then get the ego boost of thinking about what a noble person you were. In other words, it was self interest all the way down, no matter what you did.4

Along with this was the belief that enough genially selfish people working to scratch only their particular itches and to boost their own egos would somehow combine to produce the best of all possible worlds for everyone. As you may notice, this view doesn't have room or any notion of community, service, or altruism.

If that's the view you have of how the open source world works, then there is no problem with any of the examples I mentioned above. Rapid burnout and departure? Well, the level of their interest no longer was high enough for them to continue. Or maybe they just didn't achieve enough ego boosts. Either way, no problem. Exhausted volunteers? If they're doing what they want, they'll continue, and when the rewards aren't great enough they'll quit, that's the way it works. Abandoned projects or communities? Well that's what happens when there isn't enough interest. Better learn to deal with it. And those wannabe volunteers, who feel turned away? They must not want it badly enough, or maybe they're just not smart enough or pushy enough to elbow their way in.

Looking back, some of the stuff written 20 years ago along these lines comes off as an adolescent mix of Ayn Rand and liberal capitalism, and it seems mercifully to have fallen out of favor. Not that I can claim the moral high ground. Back in the day, most of us didn't really question notions like these, even though in practice most people actually behaved differently - they didn't actually put ego boosts and self interest ahead of all else.

I suppose we all benefited in some ways from our participation, but there were too many people doing too many generous and altruistic things for self interest to be the only thing, or even the main thing, driving us. But if you'd asked, that's how a lot of us would have explained how open source works.

To my mind that narrative of self interest was damaging to open source communities in general and to the Python community in particular. It incentivizes cowboy coding, flame wars, and fragmentation and discourages collaboration, inclusion, and community building. It's something that we are still struggling to get past 20 years later.

In fact Brett's famous phrase (which I have borrowed so many times), "I came for the language, but I stayed for community" very neatly sums up the way that many of us from the old days have changed our view of what matters in this world of open source and Python.

So that brings me back to the notion of gift giving as essential to our community. Again, if we think of hunter-gatherers, one of the classic examples of a gift culture, if a hunter makes a kill they share the meat with everyone. Sure, they want to eat, so there is an element of self interest in what they do, but they also share with the community. Interestingly in some Inuit cultures it's considered an insult to thank the hunter, since that would imply that they're doing something special. It's not special, it's just what you do.

True, we're not hunter gatherers, but I would argue that this pattern appeals to most of us, to most humans, actually. If you look at how people behave in our community, it's not hard to see the same ethos at work. People who contribute code do so because they can, and because it improves things for everyone. Certainly sometimes the code they give addresses a personal need, but many times it doesn't. Likewise people on the board and event organizers give a lot of labor that doesn't benefit them personally.

In turn, we can (or should be able to) count on sharing the benefits of the community. In addition to the software, it might be support and friendship, or maybe education and skills, or contacts and an increased professional network. I know I've experienced all of those, from being offered a book deal, to making so many friends in different countries, that it has driven my language learning the past few years, to the PyCon 9 years ago when my father died early on Sunday morning, and that evening several people made sure to sit with me so I wouldn't have to be alone.

The interesting thing for me about cultures that rely on gifts is that the process is so vague and messy. There's really no way to determine, say, that sharing one deer is exactly equivalent to, say, a certain number of fish, or apples, or whatever. Likewise, there's also no way to determine that 10 code patches equals one conference talk equals 3 board meetings, or whatever it might be. There's really no way to keep exact tit for tat accounts - what we can all count on is when someone is able, they will make a contribution that all can share. And in turn we will contribute what and when we can.

This messiness is not a bug, it's a feature - not knowing the timing nor the precise value of the contributions actually works to bring people together, since no one can ever say for sure that they are exactly even with anybody else. Instead there is a realization that everyone's fortunes are entangled, that we're all in this together. In other words, mutual contributions, this giving of gifts, is what helps bring people together and create community.

For me, articulating gift giving as what drives our culture, what creates our community, leads me to a couple of things that I think we can do better and that we need to be aware of if we want to preserve our Python community, and if we want it to continue to grow and flourish.

On the individual level. I think that if we consider everyone around us to be contributing to the best of their abilities, to be giving their gifts to the community, we will treat them (and ourselves) differently than if we believe that we're all out for our own self interest and don't really owe anyone a thing.

I would say that understanding that we are all benefiting from the contributions of others makes it easier to appreciate that work, the gifts they are giving. Hopefully it will also prompt us to show that appreciation, something that so many volunteers receive far too little of. And it should also make us a little less critical of others, since we understand that their contribution is a gift, freely given, not an obligation nor a transaction.

As for those shooting stars who rapidly burn themselves out, maybe reflecting on gift giving will help remind them that there is no need for any of us to give more than what we can, that what we can offer at any time is enough, and that in turn we all also will need to receive gifts from others. And maybe, I hope, some of us who've been around will be more inclined to give people who are over committing the gift of reminding them of that.

The mindset that we're a gift giving community may also help us to share the load more, to respect the gifts that others offer, and to give the gift of allowing others to take up some of the tasks we've done.

As I said earlier, rejecting someone's contribution shows a lack of respect - by rejecting their gift we are saying that we don't want them to be part of our community. Keeping that in mind, we need to be sure that there are ways for new and different people to contribute, and we need to give the gift of mentoring and guiding those people.

A part of this is that we also need to hand off leadership generously, give the gift of sharing positions of leadership. This gift benefits the giver as well as the receiver. I'm pretty sure that one reason I've been able to stay an active and involved part of our community across 20 years has been that I have had a deliberate policy to hand off the leadership of any project I've ended up leading to new people after 3-5 years.

In fact, the time to start thinking about and training your successor is as soon as you become a leader. It's not easy at first, it feels like a bit of a loss, but it helps new people grow and keeps the old-timers fresh by letting them do new things. I recommend it highly.

The other area where I think a sense of clarity about what makes our community work is vital is when it comes to money. So far I've deliberately not mentioned the dominant form we have of sharing resources - a market economy with exchanges based on money.

The thing about money, with its tendency towards exact transactions, exactly the opposite of the messiness of gifts, is that it works against connection and community. If you give me something worth $2.52 and I give you $2.52, we both know we're exactly even and the transaction is done. There's no need to continue the relationship. Transactions don't build community.

For that reason, particularly as a community, we need to be very thoughtful about how we deal with money. I'm not naive - in this world we pretty much all need money and I can testify that it's better to have a bit more of it than not enough of it. That's true of for us as individuals, for the PSF as an organization, and in general.

When we ask people to make helping our community a full time job, whether that's managing our community and events, or our infrastructure, or our coding process, those people deserve to be paid fairly, even generously. We also want to make our communities and events more inclusive, and many people need financial help to take part. Likewise, fostering communities around the world takes money, and in the foreseeable future for various reasons things will cost even more.

So clearly we need financial resources to help the community continue to grow and flourish. But I worry about any notion that we should make monetary exchange the driver of either the way that we get financial resources or the way we share them. What I mean by that is that as we confront the many problems around raising money and then using that money on behalf of the community, I think we need to think very carefully about it and be particularly wary of becoming "a business".

I don't have anything at all against business per se, mind you. I've made a living working for businesses and helping them succeed. And I appreciate the support businesses give to our community. But I would argue against our Python communities, the PSF being the leading example, ever acting like a business.

I've worked for several companies over 35 years, and no matter what HR or Marketing would like you to believe, being an employee is not like being in a community of shared contribution with your employer, nor is being a customer. If our contributors become employees, and our sponsors become customers, I believe our community will be diminished, if not destroyed.

I'm probably biased, but I think that so far, the PSF and the Python community have handled this well. The PSF has hired people to support the development of the community and help enable people to contribute more successfully in all areas. Money is spent supporting smaller regional and local groups and helping those communities grow and contribute and financial aid for PyCon and other major conferences also helps people with fewer resources make contributions on the global level.

Sponsorships have been developed which support the PSF generally, with few corporate strings attached. I believe this is the right strategy - as we interact with the business world, we should not try to become a business, but rather we should invite those enterprises to join in our world of free contribution. That means selling those organizations on hard to quantify, often intangible, benefits - a tough sell, but not impossible, and worth the effort.

These are just early days, however. As late stage capitalism becomes harsher, as Python's importance and big tech's power both continue to grow, the tension between a market economy and a community centered around gifts will also grow. In other words, I think it inevitable that there will be more pressure on us to abandon our culture of gifts and free contributions in favor of monetary transactions.

It could be companies trying to buy control over the language and/or community, it could be pressure to treat contributors and volunteers more like employees, or it could be any number of things, but in the coming years there will be many opportunities to sell out our community for one tempting offer or another.

If and when that happens, it will be up to us to decide whether we still want this community to be a place of free contribution and a time of gifts. I certainly know my answer.


  1. A Time of Gifts, Patrick Leigh Fermor, https://www.nyrb.com/products/a-time-of-gifts?variant=1094928933 

  2. My favorite book on this topic is Debt: The First 5000 Years, by Daniel Graeber, 2011, https://en.wikipedia.org/wiki/Debt:_The_First_5000_Years

  3. Callum Mcrae, quote in "Can Open Source Sustain Itself without Losing Its Soul?", Richard Gall, 16 March 2022, https://thenewstack.io/can-open-source-sustain-itself-without-losing-its-soul/ 

  4. The Cathedral and the Bazaar, Eric S. Raymond, http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ 

Stepping back from the board

The time has come...

As we head into the PSF election cycle, I'd like to let everyone know that I will not be running for re-election to the PSF Board of Directors and consequently from mid June I will no longer be serving as chair of the PSF.

Announcements like this always strike me as awkward, since they make two rather unlikely assumptions: that people will even notice, and that they will care if they do. But in the interests of transparency I'm going to go ahead as if both were true and share my reasons for this decision.

FIrst of all, I truly do believe that limited terms are good for the sustainability of an organization like ours. If someone is in a key role for too long, their inevitable departure and replacement can be unnecessarily disruptive and difficult, even with the best intentions. Of course "too long" can be hard to define, but I think it's safer to err on the side of leaving sooner rather than later. I also think it will be good for the PSF to practice handing off board leadership.

My other reason is that it's just time to move on. After five years on the board and 3 as chair, it seems like it's time to step out of that role and find something different to do, some other way to work for the Python community.

This isn't a dramatic change - I will be available to the next board as an advisor, and of course I will remain a passionate supporter of the PSF and Python communities around the world. So no, you're not getting rid of me that easily. :-D

I do hope that the PSF will continue to work on electing a diverse board, in all of the endless possible dimensions. For one target, I would love to see more representation on the board from Latin America, southern Europe, Africa, and Asia, as well as LGBTQ folks, racial and religious diversity, neurodiversity, and the rest.

If you're one of those people would help make the board more diverse but you're thinking, "yes, but there's no way that someone like me could be elected," well... I was thinking exactly the same thing when I ran for the board 5 years ago. There are no guarantees, but I believe it's worth a try, both for what you might bring and for the experience you will gain. So if that's you, get in touch - I'd be happy to talk about the board and what it involves, and offer any support I can.

It's been a privilege to work with so many amazing people on the board - we may not always have agreed on every point, but you would be hard pressed to find a group of people more dedicated to the success of the PSF and the Python community.

I'm also honored to have worked with the PSF staff as it's grown. They are truly amazing - smart, hardworking, and dedicated. I've seen their work up close, and believe me when I say that we're lucky to have them and they deserve all of the support we can give them.

As we move forward into the changes that the current crisis will bring, I have no doubt that the PSF and its board and staff will be more than up to the challenges ahead.

My time as chair of the PSF has been a lot of things for me - sometimes a challenge, often a learning experience, always an honor and a wonderful opportunity to get to know so many Python communities and their members. But above all it has been a rare and ridiculously improbable gift, something to be treasured, but also to be held lightly, and then passed on.

So long, and thanks for all the fish...

Notes on Teaching Python – Mental Models

Notes on Teaching Python – Mental Models

I admit it – I’m just an old, cranky teacher. As much I love seeing so many people all around me teaching Python, as much as I love the notion of spreading the joy of Python to various masses, there are things… things that give me pause. No, worse than pause, they give me a serious case of teacher twitch.

I start feeling the overwhelming urge to offer constructive criticism and helpful advice where none is wanted. I usually fight these urges, not wanting to be shunned by everyone as “that woman” (or something worse).

However, I also don’t want to end up in the corner muttering something like “get offa my lawn”. So I’m going to rant gently about some of these twinge inducers here.

What are we teaching, really?

I think one issue arises from a failure to ask ourselves what we really are trying to teach when we are teaching “Python”. It seems like a silly question, or a redundant one, but humor me. What are we trying to teach? Syntax? Best practices? Problem solving? TDD? OOP? What is Pythonic? Coding? Critical thinking? Computer science concepts? All of the above?

I’m pretty sure I’ve heard all of those answers at one point or another, and even given some of them. Yet I’m equally sure that something vital is missing when we talk about what we need to teach when teaching Python. And this something really holds everything else together.

The importance of a mental models

The missing “somethings” I’m thinking of (since in fact there are many of them) are mental models. We may not know every detail of how a thing works, but if we have an accurate mental model how it works, we can form some reasonable expectations about how it might work in different situations.

If I have a sound mental model of how AC current works and see that the lamp has a frayed cord, I can pretty confidently unplug it and deal with the problem. On the other hand, if I have an inaccurate mental model of how AC current works, I might either run from the room expecting the lamp to explode, or reach down and grab the bare wire. Neither is a desirable result, but yes, I’ve actually known people who fall into both categories.

The same is true in Python and coding. If we have an accurate way of thinking about a feature of the language, we stand a much better chance of getting code that works as desired. If we have faulty mental models, then the coding equivalent of electrocution or irrational avoidance awaits.

Take “variables,” please

For example what about “variables”? Yes, I agree that the term “variable” is questionable in Python. Yes, I prefer either “name” or “label”. However, it seems pretty much everyone calls them variables at some time or another, which may well be part of the problem. Several times now I’ve seen newcomers to coding being taught that about “variables” in Python. And many of those times I’ve seen the explanation that a variable is a “container that holds a value.” Or, as I used to say when I taught C, they’re told that a variable is like a bucket.

For C this makes some sense. And while no one should argue too much with the notion that the contents of a variable must go somewhere, in fact thinking of Python variables as containers is an inaccurate model – names in Python are more like post-its than buckets. But what makes the notion of variables as buckets even more insidious is that it seems to work well enough at first that people get used to thinking this way, and then pass it along.

Consider the following mindless code:

    a = 1
    b = a
    c = b
    print(a, b, c)

So far, so mindless. If you ask people what you get, they will not have a problem saying 1 1 1.

But suppose you then add the line

   b = 2

and ask about print(a, b, c)?

The followers of the bucket camp will usually (and correctly) say that the result is 1 2 1. In fact, there may be some confusion about what the “contents” of c are, but if you are thinking buckets, the answer makes sense.

But what about a mutable object? Suppose we have this:

    a = [1, 2, 3]
    b = a
    c = b
    b[1] = 5
    print(a, b, c)

Here the members of the bucket brigade are often stumped. In my experience I have been stunned at how many beginning (even intermediate) Python coders are surprised by the actual output of [1, 5, 3] [1, 5, 3] [1, 5, 3]. If variables are containers, how on earth can changing the contents of one change the others?

But if instead they are names that point to objects, the right answer makes sense. Once they have a better mental model of how names work in Python, such surprises (and the attendant bugs) become much rarer.

Let me be clear, this example isn’t the only case of poor mental models in teaching Python. I’ve picked on this example because it’s so fundamental and, in my experience at least, so common.

The question is not if our students will create mental models or not – we all form mental models as we learn. It’s our job as teachers to be thoughtful and help our students form useful and accurate ones.