@treyhunner@mastodon.social
@treyhunner@mastodon.social avatar

treyhunner

@treyhunner@mastodon.social

#Python & #Django educator & team trainer

I help folks sharpen their Python skills with https://PythonMorsels.com🐍🍪

#pythonoddity

Also a #humanist #YIMBY who is attempting more ethical eating (#vegetarian, not yet #vegan) and thinks #economics is highly underrated, but I don't post about those topics very often.

he/him

This profile is from a federated server and may be incomplete. Browse more on the original instance.

wsvincent, to random
@wsvincent@fosstodon.org avatar

I wonder if there's room for something between short tutorials and courses. Maybe "recipes" where I just show how to do common intermediate-ish Django tasks, but don't have to explain all the steps the way I normally do? So not docs that are abstract, still step-by-step, but more like here's the recipe and there are links to go deeper on the "why" if you need it.

treyhunner,
@treyhunner@mastodon.social avatar

@CodenameTim I'm planning to eventually integrate screencasts and mini exercises, which might fit the dream that @wsvincent's has even closer.

I do think this is sorely needed for Django! 💗

treyhunner, to python
@treyhunner@mastodon.social avatar

What's the difference between local and global variables in ?

https://youtu.be/OJa5QIeiNfQ

treyhunner, to python
@treyhunner@mastodon.social avatar

In we often rely on "truthiness" in our boolean expressions.

Empty strings, empty lists, and None are all "falsey".

https://youtu.be/GVrZl7skiWg

treyhunner, to random
@treyhunner@mastodon.social avatar

Python doesn't have type coercion... at least not the way many programming languages do.

Most operations leave type conversions up to the objects being operated on.

You can add an int to a float because floating point numbers "know" how to handle that. But integers and strings don't know how to add themselves together.

https://youtu.be/bYaulAzoU3Y

treyhunner, to random
@treyhunner@mastodon.social avatar

New screencast: How to make a context manager 📺🐍🎛

I've taught this topic for years, but this is the first time I've whittled this all down to just 5 minutes.

https://pym.dev/creating-a-context-manager/

treyhunner,
@treyhunner@mastodon.social avatar

@siddhantgoel agreed! Hoping to do a separate screencast on that.

treyhunner, to python
@treyhunner@mastodon.social avatar

Lists, strings, numbers, functions, modules, and classes are all objects in Python.

In , everything is an object. ♾️

https://youtu.be/_0lGCQvieV8

treyhunner, to python
@treyhunner@mastodon.social avatar

What feature would you have trouble explaining to a new programmer?

(If you think you CAN explain that feature, feel free to reply to replies with your own new-programmer-oriented explanation)

treyhunner,
@treyhunner@mastodon.social avatar

@adamchainz good one! 😅 I have found some non-trivial uses for match/case but there are some corners that I would really struggle to explain. 😬

treyhunner,
@treyhunner@mastodon.social avatar

@orsinium yup. There is more to arguments than is worth learning/teaching in an introductory course. I always include a preview of some of the more complex stuff and a disclaimer that you don't need to know most of it to get started and you shouldn't try to memorize most of it beyond positional vs keyword and defaults (until you find yourself needing it...).

treyhunner,
@treyhunner@mastodon.social avatar

@kleaders great one!

Comprehensions are one of those features where throwing a few explanations at the wall can be helpful because different mental models work better for different folks.

Here's one explanation of comprehensions:

The original comprehensions from other languages come from set builder notation in math.

[ x*2 | x <- numbers, x%2==1 ]

But we don't like symbols in so we instead write that as:

[x*2 for x in numbers if x%2 == 1]

treyhunner,
@treyhunner@mastodon.social avatar

@kleaders here's another explanation of 's comprehensions.

If you have a "for" loop that consist solely of an append, an optional "if" that the append is within, and maybe a nested "for" loop in your loop, you can copy-paste your way into a comprehension.

The expression you're appending comes first. Every other expression remains in the same order.

I recommend folks start their comprehension journey by writing the "for" loop first (since it's familiar) and then copy-pasting into it.

treyhunner,
@treyhunner@mastodon.social avatar

@kleaders It may seem odd to copy-paste your way from a loop, but it's not meant to be a permanent technique.

The idea is to anchor what you're less familiar with (the comprehension) on the syntax of what you know (the loop).

The syntax is weird! It uses the keywords "for" and "if", which makes it look like an inside-out "for" loop, even though it's really something separate.

More:
• Short: https://pym.dev/turning-loop-list-comprehension/
• Longer: https://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/
• Longer-er: https://trey.io/comprehensions

treyhunner,
@treyhunner@mastodon.social avatar

@kleaders you're welcome!

treyhunner,
@treyhunner@mastodon.social avatar

@kleaders @meejah big +1 to breaking over multiple lines. I pretty much always prefer that.

Something to note is that unfortunately using the Black autoformatter will turn them back to one-liners unless they're over the maximum like length you have set. 😢

mborus, to random
@mborus@mastodon.social avatar

Had a lot more "fun" with today. Main problem was that I can't make a div element behave like a button inside a form. (Which I needed to refactor a JavaScript mess without changing the CSS too much)

The current solution: Writing vanilla JavaScript (see https://htmx.org/api/) - then tacking hx-on="click: myJSfunc(...)" onto the divs and doing the htmx.ajax request from my custom JS code.

Feels very hacky, but it seems to work so far.

treyhunner,
@treyhunner@mastodon.social avatar

@mborus yikes. That's a weird issue. That seems like it should be possible to do. 🤔 Any idea whether that's a known bug?

treyhunner,
@treyhunner@mastodon.social avatar

@mborus I'm also really liking . I use it in a handful of places throughout the pythonmorsels.com app, along with Alpine.js for non-server actions and quite a bit of custom JavaScript for more complex things that neither Alpine nor HTMX can replace.

Initially I replaced a few non-HTMX widgets with HTMX ones and the HTMX version was SO much more maintainable.

treyhunner, to python
@treyhunner@mastodon.social avatar

Python tip 💡

If you just ran an expression in the REPL and you'd like to capture its value into a variable, you don't need to run it again!

You can use the _ variable to get the value of the last REPL output!

You'll also sometimes see _ used as a throwaway variable:

>>> from random import randint
>>> numbers = [randint(1, 5) for _ in range(10)]

_ works in the built-in Python REPL and pretty much all third-party REPLs.

Try _ out yourself in a REPL: https://pym.dev/repl

random.randint used in a list comprehension to generate a range with _ used as a throwaway variable. See code at https://pym.dev/p/3328x

treyhunner, to random
@treyhunner@mastodon.social avatar

TIL you can use a dict for slots in Python 💡

https://fosstodon.org/@orsinium/110780666371693920

cenbe, to python
@cenbe@mastodon.sdf.org avatar

Just learning ... it doesn't have constants? Really? And you're supposed to simulate them by using a naming convention? You're kidding me, right?

treyhunner,
@treyhunner@mastodon.social avatar

@diji @cenbe the fact that variables are pointers throws a wrench into the ability to have useful constants.

JavaScript has the same problem but they decide to make constant variables anyway. So in JavaScript you can have a constant variables whose value can change. 😬

I prefer Python's decision. Either way is a trade-off (as was the initial "variables are pointers" decision). ⚖️

treyhunner, to python
@treyhunner@mastodon.social avatar

Need a multi-line string in but don't want to include a big block of manually dedented text?

Use textwrap.dedent! 🎁⬅️

Here's some code that does NOT use dedent:

def copyright():
print("""\
Copyright (c) 1991-2000 ACME Corp

Copyright (c) 2000-2030 Cyberdyne"""
)

Here's the same code with dedent:

from textwrap import dedent

def copyright():
print(dedent("""\
Copyright (c) 1991-2000 ACME Corp

Copyright (c) 2000-2030 Cyberdyne\
"""))

Better, right?

treyhunner, to python
@treyhunner@mastodon.social avatar

You can use a docstring to add documentation to any function, class, or module you make in

https://youtu.be/R6diu-uMUi4

treyhunner, to python
@treyhunner@mastodon.social avatar

If you were to mentor a beginner coder, what would be your first lesson?

treyhunner, to python
@treyhunner@mastodon.social avatar

All iteration is equivalent in .

If you loop over a dictionary, you get keys:

>>> d = {'A': 0, 'B': 0}
>>> for x in d: print(x)
...
A
B

Same if you convert it to a list:

>>> list(d)
['A', 'B']

Or use the string join method on it:

>>> " ".join(d)
'A B'

Or use the enumerate function:

>>> for item in enumerate(d):
... print(item)
...
(0, 'blue')
(1, 'red')

Or a comprehension:

>>> [x+'!' for x in d]
['blue!', 'red!']

Or even tuple unpacking:

>>> a, b = d
>>> b
'B'

treyhunner, to python
@treyhunner@mastodon.social avatar

I often see my students use the split method with a single space character:

>>> x.split(" ")

Usually using the split method without any arguments is preferable:

>>> x.split()

Why?

Well, the default string delimiter for splitting in isn't "space" but "any amount of consecutive whitespace":

>>> x = "Python is
\tneat."
>>> print(x)
Python is
neat.
>>> x.split()
['Python', 'is', 'neat.']

Plus split without any delimiter strips whitespace from the ends of a string!

  • All
  • Subscribed
  • Moderated
  • Favorites
  • JUstTest
  • kavyap
  • DreamBathrooms
  • thenastyranch
  • magazineikmin
  • tacticalgear
  • khanakhh
  • Youngstown
  • mdbf
  • slotface
  • rosin
  • everett
  • ngwrru68w68
  • Durango
  • megavids
  • InstantRegret
  • cubers
  • GTA5RPClips
  • cisconetworking
  • ethstaker
  • osvaldo12
  • modclub
  • normalnudes
  • provamag3
  • tester
  • anitta
  • Leos
  • lostlight
  • All magazines