Want to get a head start on the artificial intelligence wave? Among other things, you’ll need to get a solid understanding of Python and machine learning, and the $10 level of Humble Bundle’s “Cookbooks for Coders” bundle has three great books to get you started:
Plus, you get seven other books covering a number of topics. I personally would benefit from the React, PowerShell, Raspberry Pi, and Regular Expression cookbooks.
I love the “cookbook” format, since it lives in the space between reference books, which are often too dry and provide no usage examples, and tutorials, which can often be a little too directed at solving one problem. Cookbooks give you just enough information to learn how to use a particular language or framework feature so that you can apply that knowledge to solving your particular problem or building the app that you have in mind. I find that I learn the most about a language or framework when I use material from cookbooks and other people’s code in building my own application ideas.
The “Cookbooks for Coders” Humble Bundle is available for another 13 days at the time of this writing. For ten dollars, it’s a pretty sweet deal. I’ve already picked it up, and if you want to get in on some of the machine learning opportunities that are already coming in fast and furious, you should too!
The 5th annual Python Web Conf— an online conference for mid-level to advanced Python developers — takes place next week, from Monday, March 13th through Friday, March 17th. Not only is Auth0 by Okta (where I work) one of the sponsors, but I’ll be in attendance!
My teammate, Jessica Temporal, will deliver one of the keynotes on Monday, March 13th at 1:00 p.m. EDT (UTC-4, and yes, we’ll have just moved to Daylight Saving Time). Her keynote is titled Go With the Flow, and it’s about authentication and authorization flows, which happens to be something that we in Okta and Auth0 are pretty good at.
Juan Cruz Martinez and I will also be in attendance and available for chats throughout each conference day and during the Zoom Breakout Rooms sessions at the end of each of days 1 through 4 — Monday, March 13th through Thursday, March 16th.
Want to find out more about Python Web Conf 2023?How about checking out these 90 videos from Python Web Conf 2022? You’ll find all sorts of topics covered, from the nuts and bolts of the Python programming language, libraries, and tools, but also subjects such as CI/CD, data science, machine learning, better processes, writing documentation, and how to be a better programmer.
As for this year’s conference, Python Web Conf 2023 has 5 tracks:
US$199 if you’d like to attend live, be able to join tutorial sessions, partake int he online social events and have exclusive access to the recordings for 90 days.
US$100 if you only want post-conference videos available to you for 90 days after the event.
There’s also a grant program if you need assistance.
Videos of the sessions will be posted publicaly on YouTube following the 90-day period.
The conference takes place from Wednesday, April 19th through Friday, April 21, with workshops on Wednesday and the main conference taking place Thursday and Friday. Here’s the agenda.
I haven’t been able to find out more about this conference, but you might be able to glean more from the following Twitter accounts:
Teaching a person how to spell out numbers involves a lot of repetition. Tampa Bay’s own Jack Hartmann, whose children’s educational YouTube channel has over a million subscribers and 300 million views, knows this. He’s got a video that teaches kids the words for the numbers 0 through 10:
Don’t underestimate the power of videos for kids — Jack’s laughing all the way to the bank. This online estimator says that his YouTube channel should be earning about $70,000 every month, and keep in mind that his particular line of work has probably benefited from everyone being stuck at home. I may have to do something similar with the accordion when this software fad passes.
If you just wanted to be able to convert any number from 0 through 10 into word form in Python, you could use a list…
…and if you wanted the number 3 in word form, you’d use this:
# This is in the Python REPL
>>> number_words[3]
'three'
You wouldn’t want to take this approach for a larger set of numbers, and you probably wouldn’t want to code it yourself. Luckily, you don’t have to do this in Python, thanks to the inflect.py module.
Using inflect.py
inflect.py is a module that does all sorts of processing to make your programs’ text output grammatically correct. If you hate seeing output like this…
You have 1 items in your cart.
…or this…
You have a egg in your inventory.
…you can use inflect.py to automatically use the correct singular or plural form, use “a” or “an” when appropriate, and so much more.
(I’ll cover inflect.py in greater detail in a future article.)
In addition to all these grammatical goodies, inflect.py can also be used to convert numbers to words.
To use inflect.py, you’ll need to install it first. The simplest way to do so is with pip:
pip install inflect
Once installed, you can use it in your Python programs. Here’s an example:
import inflect
inflector = inflect.engine()
words = inflector.number_to_words(54321)
print(words)
It produces this output:
fifty-four thousand, three hundred and twenty-one
The number_to_words() method has a number of optional parameters that are useful in certain circumstances. For instance, there’s the boolean wantlist parameter, which causes the word output to be broken into “chunks”:
words = inflector.number_to_words(54321, wantlist=True)
It produces this output:
[‘fifty-four thousand’, ‘three hundred and twenty-one’]
Suppose you want the number to be converted into its individual digits as words. You’d use the group parameter:
# This is in the Python REPL
>>> inflector.number_to_words(54321, group=1)
'five, four, three, two, one'
>>> inflector.number_to_words(54321, group=2)
'fifty-four, thirty-two, one'
>>> inflector.number_to_words(54321, group=3)
'five forty-three, twenty-one'
What if you’re using the group parameter set to 1, but want to get all UK English and have it use the word “naught” for zero? Or maybe you want your program to sound like a film noir gangster and say “zip” instead? Or you want it recite a phone number and say “oh”? That’s what the zero parameter is for:
# This is in the Python REPL
>>> inflector.number_to_words(13057, group=1, zero='naught')
'one, three, naught, five, seven'
>>> inflector.number_to_words(13057, group=1, zero='zip')
'one, three, zip, five, seven'
>>> inflector.number_to_words(8675309, group=1, zero='oh')
'eight, six, seven, five, three, oh, nine'
The one parameter does the same thing, but for the digit 1:
# This is in the Python REPL
>>> inflector.number_to_words(13057, group=1, one='unity')
'unity, three, zero, five, seven'
Want to get all Star Trek? Use the decimal parameter to change the default decimal word to “mark”.
# This is in the Python REPL
>>> coordinates = inflector.number_to_words(123.789, group=1, decimal='mark')
>>> print(f"Ensign Crusher, set course to {coordinates}. Engage.")
Ensign Crusher, set course to one, two, three, mark, seven, eight, nine. Engage.
A lot of style guides tell you to spell out the numbers zero through ten, and use the number form for numbers 11 and greater. The threshold parameter makes this easy:
# This is in the Python REPL
>>> inflector.number_to_words(9, threshold=10)
'nine'
>>> inflector.number_to_words(10, threshold=10)
'ten'
>>> inflector.number_to_words(11, threshold=10)
'11'
Go ahead — import inflect.py and play with it. There’s a lot of power in that module, and it goes way beyond just converting words to numbers!
Converting a number into its word form — for example, converting 1,234,456 into one million, two hundred and thirty-four thousand, four hundred and fifty-six — used to be a really painful exercise in programming. These days, there are libraries that save you from having to do this, and in the case of Swift, this functionality is built into its standard library in the form of the NumberFormatter class. Not only will it convert numbers into words, but it will also do so for many languages!
Open a Swift playground in Xcode and enter the following code:
// Swift
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
let number = 87654
let spelledOutNumber = formatter.string(for: number)!
print("\(number) spelled out is \(spelledOutNumber).")
Run the playground code, and you’ll see this:
87654 spelled out is eighty-seven thousand six hundred fifty-four.
Having come from the world of C, where you format strings using printf() and formatting strings, and later from other languages where you use whatever formatting method its string class provides, I’ve ignored most of Swift’s classes that derive from Formatter — with one notable exception: DateFormatter, which is indispensable when working with dates and times.
I’m now looking for an excuse to use this capability.
As I typed “DateFormatter” a couple of paragraphs above, I remembered that DateFormatter had a locale property. It’s for ensuring that any dates you present are in the correct form for the locale:
I wondered:
Does NumberFormatter have a locale property?
What happens if I changed it to something other than my system’s default of US English?
So I changed the code in my playground to the following:
// Swift
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
formatter.locale = Locale(identifier: "fil_PH")
let number = 87654
let spelledOutNumber = formatter.string(for: number)!
print("\(number) spelled out in Filipino is \(spelledOutNumber).")
I ran the code and saw this…
87654 spelled out in Filipino is walóng pû’t pitóng libó’t anim na daán at limáng pû’t ápat.
…and my response was “Ay nako!” (translation: OMG!)
How about Korean?
// Swift
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
formatter.locale = Locale(identifier: "ko_KR")
let number = 87654
let spelledOutNumber = formatter.string(for: number)!
print("\(number) spelled out in Korean is \(spelledOutNumber).")
The output:
87654 spelled out in Korean is 팔만 칠천육백오십사.
My response: 세상에 (“Sesange!”, which is pretty much Korean for OMG!)
// Kotlin
class ProgrammingLanguage(
var name: String,
var creator: String,
var yearFirstAppeared: Int,
var remarks: String,
var isInTiobeTop20: Boolean) {
fun display() {
println("${name} was created by ${creator} in ${yearFirstAppeared}.")
println("${remarks}")
if (isInTiobeTop20) {
println("This language is in the TIOBE Top 20.")
}
println()
}
}
Creating an instance is pretty straightforward:
// Kotlin
val currentLanguage = ProgrammingLanguage(
"Pascal",
"Nikalus Wirth",
1970,
"My first compiled and structured language. Also my first exposure to pointers.",
false)
When you run the code currentLanguage.display(), you get:
Pascal was created by Nikalus Wirth in 1970. My first compiled and structured language. Also my first exposure to pointers.
Suppose you want to change all the properties of currentLanguage and then display the result. If you’re used to programming in other object-oriented programming languages, you’d probably do it like this:
// Kotlin
currentLanguage.name = "Miranda"
currentLanguage.creator = "David Turner"
currentLanguage.yearFirstAppeared = 1985
currentLanguage.remarks = "This was my intro to functional programming. It’s gone now, but its influence lives on in Haskell."
currentLanguage.isInTiobeTop20 = false
currentLanguage.display()
For the curious, here’s the output:
Miranda was created by David Turner in 1985. This was my intro to functional programming. It’s gone now, but its influence lives on in Haskell.
Now, that’s a lot of currentLanguage. You could argue that IDEs free us from a lot of repetitive typing, but it still leaves us with a lot of reading. There should be a way to make the code more concise, and luckily, the Kotlin standard library provides the with() function.
The with() function
One of the first programming languages I learned is Pascal. I cut my teeth on Apple Pascal on my Apple //e and a version of Waterloo Pascal for the ICON computers that the Ontario Ministry of Education seeded in Toronto schools.
Pascal has the with statement, which made it easier to access the various properties of a record (Pascal’s version of a struct) or in later, object-oriented versions of Pascal, an object.
Kotlin borrowed this trick and implemented it as a standard library function. Here’s an example, where I change currentLanguage so that it contains information about BASIC:
// Kotlin
with(currentLanguage) {
name = "BASIC"
creator = "John Kemeny and Thomas Kurtz"
yearFirstAppeared = 1964
remarks = "My first programming language. It came built-in on a lot of ‘home computers’ in the 1980s."
isInTiobeTop20 = false
}
This time, when you run the code currentLanguage.display(), you get…
BASIC was created by John Kemeny and Thomas Kurtz in 1964. My first programming language. It came built-in on a lot of ‘home computers’ in the 1980s.
…and the code is also a little easier to read without all those repetitions of currentLanguage.
Suppose you wanted to print the string “Hello there!” three times. In any language that borrows its syntax from C, you’d probably use the classic for loop, as shown below:
// C99
for (int i = 0; i < 3; i++) {
printf("Hello there!\n");
}
// JavaScript
for (let i = 0; i < 3; i++) {
console.log("Hello there!");
}
With Kotlin’s for loop, you have a couple of options:
// Kotlin
// Here’s one way you can do it:
for (index in 0 until 3) {
println("Hello there!")
}
// Here’s another way:
for (i in 1..3) {
println("Hello there!")
}
If you’re used to programming in a C-style language, you’ll probably reach for a for loop when you need to perform a task a given number of times. The Kotlin language designers noticed this and came up with something more concise: the repeat() function:
repeat(3) {
println("Hello there!")
}
As you can see, using repeat() give you a shorter, easier to read line than for. And in most cases, shorter and easier to read is better.
Do you need to know the current iteration index? Here’s how you’d get that value:
fun main() {
repeat(3) { iteration ->
println("Hello there from iteration $iteration!")
}
}
Remember, you can use whatever variable name you want for that index, as long as it’s a valid name:
fun main() {
repeat(3) { thingy ->
println("Hello there from iteration $thingy!")
}
}
Note that repeat() is for performing a task a known number of times, without exceptions. It’s a function that takes a closure, not a loop structure. This means that the break and continue statements won’t work:
// This WILL NOT compile!
fun main() {
repeat(3) { iteration ->
// 🚨🚨🚨 You can’t do this 🚨🚨🚨
if (iteration == 1) {
break
}
// 🚨🚨🚨 You can’t do this, either 🚨🚨🚨
if (iteration == 2) {
continue
}
// “break” and “continue” work only
// inside a loop, and repeat()
// *isn’t* a loop...
// ...it’s a *function*!
println("Hello there from iteration $iteration!")
}
}
@kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0 until times) {
action(index)
}
}
To summarize: If you need to perform a task n times in Kotlin — and only n times — use repeat instead() of for!