Show newer

@f @jefframes It's not Scratch's fault, but it's an unintended consequence that its overuse may be causing more harm than good, for some children, at least

@f @jefframes Often, the problem with Scratch is that it's overused and children get bored of it - and that age they may think Scratch = Coding so they think they're bored of coding…

Teaching #Python and interested in adding physical computing? Or using the BBC #microbit in class and wanting to explore text-based coding? I'm co-hosting two more webinars this month on the new micro:bit Python Editor.
It's designed to overcome barriers to learning with a simulator, reference section with code snippets you can drag and drop into your code, auto-complete, indentation highlighting and more.
Webinar details here: microbit.org/news/events/webin
#microPython

Do you know the offside rule? Sure? To have some fun, I'm writing a quiz using Python's `turtle`

This is what it looks like so far (and no, I'm not bothering with fancy graphics – life's too short)

In this video:
- you can see direction in which team is attacking from the arrows
- each snapshot shows when player with the ball kicks the ball forward
- program (hopefully) detects whether it's offside or not
- there are 15 (random) scenarios in this video

Still to do:
- deal with when forward player is in own half (no offside)
- deal with when forward player is the one with the ball (no offside)
- turn into a quiz
- write article for The Python Coding Book blog about it to document the code - there are some interesting aspects I'm using in the code that hopefully some will find useful.

@JHB17 @fatrat A good way to explore this is to try it out. Create a script, let's call it `test.py` and include the following variables:

`some_variable = 10`
`_another_variable = 20`
`__yet_another_one = 30`

Then try `from test import *` in the REPL/Console. You'll see that only `some_variable` is public so only that variable is imported.

But now, add the following at the top of the script:

`__all__ = ["_another_variable", "__yet_another_one"]`

and try `from test import *` in a **new** REPL/Console (not the same one as before, as the old version is already imported there)

@fatrat In fact, here's what the official Python style guide, PEP 8, says about the matter:

"Wildcard imports (from <module> import *) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools."

peps.python.org/pep-0008/#impo

@fatrat Yes, you do find that a lot, but that doesn't make it good. Many things are a matter of preference, but this is one of those things where it's now generally considered best to avoid.

You can see what's imported by accessing the `__all__` property, so:

`tkinter.__all__`

If a module doesn't have this defined, then all the non private names will be imported. But if a module has `__all__` defined, then only what's included in `__all__` will be defined

@JHB17 @fatrat Although in general, it's always best to avoid `from ... import *`

@erikdesmedt @out_of_cheese Correct, and in the standard Python REPL, the underscore stores the last value, so you don't need to assign it, either

Weird Python line of the day:

`>>> [10, 20, 15, 12, 9][_]`
`[20, 15]`

**How can you achieve this?**

_Note: this is not something you'll want to do in real code, just a Python curiosity!_

@fatrat `from … import *` doesn’t import everything. The module’s author can decide what’s included.

But note that it’s generally considered bad practice to use `from … import *` as it dumps lots of stuff into the main namespace. It is safer to keep namespaces separate

Work in progress - An Offside Rule Quiz using Python's `turtle`

Will aim to get it done in the next few days… (will write it up as an article, too)

For those who don't follow football (that's soccer for some around the world), the offside rule is one of those "notorious" rules that not everyone gets.

This is a great resource for teachers who are eager to teach Python. Teaching Python teachingpython.fm/ #python #edutooter #edtech @edutooters

There are often heated arguments, often with many holding "absolutist" positions, on various topics in . However, as with other areas of life, it's the more nuanced pragmatic view that (should) prevail.

Let's take static and dynamic typing. There are reasons why not all leading languages use either one or the other. They're different tools for different jobs.

If you need to prioritise safety in production code: static typing may be your choice.

If you want to prioritise prototyping speed and writing code rapidly, including by programmers who don't just program but use coding as part of other professional skills, dynamic typing options may be better.

It's all about using the right mindset for the right language. If someone is used to coding in C++, say, and tries to write Python code in the same way they write C++, that can (and will) lead to problems! The same is true the other way round, too, of course.

Take duck typing in languages such as : that's a mindset–prioritising what an object can do rather than what it is. Once you get it, and you think about whether something is a sequence or an iterator rather than a list or string, say, then you're better placed to code in Python

There's no "this is the better one", instead, there's "this is the better one for this application"

@lewischuang thank you. My philosophy is guided by my experience with teaching technical subjects, first teaching Optics to optometry undergrads, and then years of teaching coding to people of all ages (including kids). I think we all have our own styles of teaching. There’s no good or bad, it’s whatever works best for each learner.

One of my (many) 2023 plans is to add finishing touches to ThePythonCodingBook.com and make it available in some other format, too:

- ebook only
- self-published book
- published via a publisher

My preference is the latter but publishers shy away from beginners’ books…

I’d need to spend time carefully pitching to them why I think it’s different from other books. Not sure I can justify time to do that

More thinking needed

In the meantime, the content is all there for beginners to enjoy, and many have done just that

thepythoncodingbook.com/what-p

@brwillems A big part of the answer is memory management. A generator doesn't store all the values in memory, it fetches them or creates them as and when they're required.

Here are two scenarios: you're reading data from a large data set stored outside of your program (let's say a large CSV). A generator allows you to represent the "whole data set" in your program, but only needs memory for one item at a time.

Or, you have a large set of data stored in memory, but want to get lots of subsets of it - all the names starting with P in a large list of names, all those 5 letters long, and so on. Each subset can be a generator which uses the same data set (the original one) without duplicating memory

One thing that many find very confusing when they first learn about generators is that once they're exhausted they're, erm, exhausted.

Eh?!

Let's see what this means with an example. Let's start with a list, first:

`numbers = [item for item in range(10)]`

`# Loop through numbers`
`for number in numbers:`
`print(number)`

`# And let's loop one more time…`
`for number in numbers:`
`print(number)`

We've used a list comprehension to create a list of numbers–it's not the most exciting list you'll see, but it will do here

You're them looping through the list twice, printing out the values each time

Here's the output from this code:

0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9

I did say it's not an exciting list. I know!

The numbers are printed out twice. Of course they are, since you've repeated the loop twice

Let's see what happens with a generator instead of a list:

`# Notice that we've now made this a generator`
`numbers = (item for item in range(10))`

`# Loop through numbers`
`for number in numbers:`
`print(number)`

`# And let's loop one more time…`
`for number in numbers:`
`print(number)`

Notice how we're now using parentheses (round brackets) instead of square brackets when creating `numbers`

This creates a generator

If you `print(type(numbers))` you'll get:
`<class 'generator'>`

and if you `print(numbers)`:
`<generator object <genexpr> at 0x103309ff0>`

So, what's the output from the two `for` loops?

Let's find out:

0
1
2
3
4
5
6
7
8
9

The numbers are only printed out once. The generator was "used up" when you looped through it the first time, so you can't use it again

Here's why this happens (very abridged version):

A generator doesn't store the data within it. Instead, it refers to data which is stored or created elsewhere

So, when you try and fetch the first item in `numbers`, the generator fetches `0` and it now "knows" it's taken the first value…

So the next time you need a value from `numbers`, it will get the second one, and so on…

Once it fetches the last item, there's nothing left
The generator is exhausted
When you try to fetch another item, there's nothing there

Think of a generator as single-use

Today for #projects: another hashtag I coined, the #pythonoddity hashtag.

Years ago I decided I was going to try tweeting one "python oddity" (anything that might be a gotcha for a new Python user). I decided to make a hashtag for it: #pythonoddity.

I still collect #python oddities but I don't share them as regularly as I used to. Maybe I should start that hashtag up again here?

Here's a collection of some of my favorite #pythonoddity tweets over the years: twitter.com/i/events/871564334

Show older
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.