Master Python objects (and understand how they work)

I’ve been teaching Python for many years now, and it never ceases to amaze me to discover just how many people are able to use Python without ever having really learned it.

In particular, there are lots of people writing and using Python objects who assume that classes and instances in Python work just like those in Java and C#, but with less syntax.

For the most part, they can make those assumptions and not suffer too much.  But then, if something goes wrong… well, they’re at a loss to explain how and why things didn’t work.

And then little things nag them: Why does “self” need to be the first parameter in a method? And when we set a variable inside of a class definition, are we setting the default for the instances? (Answer: No, because you’re setting a class attribute.)  How does inheritance really work?  And how does super() work in Python?

Knowing the answers to these and other questions are the key to becoming a more fluent Python developer. That’s important, because fluency will allow you to do more in less time, to write more expressive and powerful code, and to write code that can be changed and maintained more easily.

I’ve taken my lessons and exercises from my intro Python class and turned them into a new online class, “Object oriented Python.”  The course assumes that you’re familiar with basic Python data structures and functions, but otherwise starts with the basics of object-oriented programming, through inheritance and operator overloading.

In more than 4 hours of video lectures, and with 15 exercises, I walk you through how Python’s object system works, and how you can make it work for you.

This course is for you if:

  • You’re a Python developer unfamiliar with objects
  • You’ve been cutting, pasting, and editing Python code for years from Stack Overflow and blogs, without really understanding how objects work
  • You’re new to Python, but experienced with objects in another language, such as C#, C++, or Java

This is the same material I teach at companies like Apple, Cisco, IBM, Intel, PayPal, Western Digital, and VMWare.  I’m booked solid 8 months in advance with training at these companies  — but you can get these lessons, and improve your Python coding, in the coming minutes.

The course includes:

  • More than four hours of lecture/screencasts
  • 15 exercises, including extensive walk-throughs of the solutions
  • PDFs of the slides I use when teaching about objects
  • The Jupyter notebook I used when live-coding the course
  • Any and all updates I make to this course in the future, via my “forever free” policy

Also: You get access to my online office hours, given every 3-4 weeks, online, to students in all of my classes.  Come and ask your Python questions!  Or submit them, and I’ll answer them for you in video.

Not sure?  Go to the course page; a number of the lessons are available for free preview.

Click here to order “Object-oriented Python”

This course, like all of my others, comes with a 100% money-back guarantee.  I also offer discounts for students and pensioners, group discounts, and parity pricing for people living in any country outside the 30 wealthiest in the world.  Just e-mail me to get the appropriate coupon codes.

If you’re a Python developer and have been unsure about how to use Python objects, this is your chance.  Order “Object oriented Python,” and become a more fluent Python developer today.

Still not sure?  Send me e-mail, at reuven@lerner.co.il, and let me know.  I’ll be delighted to answer your questions.

Freelancers Show #300 — live!

As you may know, I’ve been a panelist on the Freelancers Show podcast for a few years.  It’s one of the high points of my week to chat with my co-panelists, discuss various aspects of freelancing/consulting, and to interview interesting people who can help us improve our freelancing careers.

I’ve been consulting since 1995, but I think that my business has improved greatly thanks to the advice I’ve gotten from the show, and from the discussions we’ve had.

This coming Tuesday, we’ll be recording our 300th show. To celebrate, we’re making it a live webinar, in which we’ll take questions from … well, anyone who wants to ask!

(The show will also be recorded and available as usual.)

So, if you’re a freelancer/consultant, or if you’re thinking about taking the plunge, or just curious, or just want to see what I look like — well, join us!  You can sign up at the Crowdcast site here:

https://www.crowdcast.io/e/tfs300

If you can’t make it, then we would still love to get your questions.  Write them on the Crowdcast page, or leave them as comments here.  I promise we’ll try to answer them all!

Announcing my new Python course, “Comprehending Comprehensions”

What’s the hardest part of Python to understand?

For nearly 20 years, I’ve been teaching Python to engineers at companies around the world. And if I had to say what most confuses my students, it’s list comprehensions.

And yes, if you’re wondering, set and dict comprehensions are equally confusing.

Comprehensions are both powerful and compact. The syntax, however, is far from obvious. Moreover, it’s not always clear just when or why you should use comprehensions, and when you should instead use a regular “for” loop.

Experienced Python developers know that there is a difference between comprehensions and “for” loops, even if it isn’t obvious to newcomers. Those experts also know that comprehensions are an essential part of a Python developer’s toolbox. It’s a rare day on which I won’t use a comprehension in my Python programming.

Among other things, comprehensions can:

  • help you to convert sequences from one type to another
  • make it easy to extract information from logfiles
  • rearrange data inside of complex data structures
  • create lists, sets, and dicts from files

So, how can we help newcomers, who see comprehensions as some combination of weird, unnecessary, and hard to understand? If you know me, then you already know the answer: Clear explanations, followed by lots of practice.

I’m thus delighted to announce the launch of “Comprehending comprehensions,” an online course that teaches Python developers how and why to use comprehensions.

This is an Internet version of a class which I have taught more than 100 times at companies around the world. Through nearly two hours of video and more than 15 exercises, you’ll learn how, when, and why to write and use comprehensions.

If you’re familiar with Python’s basic data types (strings, lists, tuples, dicts, and sets), reading from files and writing simple functions, but don’t yet feel comfortable using comprehensions, then this course is for you: You’ll come out of the course knowing how to write faster, cleaner, and more robust Python code. You’ll know how to handle common situations with data structures and files. And you’ll be better prepared to read and debug code written by others.

In addition to the videos and exercises, this course comes with the slides I use at my in-person training, and the input files you’ll need to solve the exercises.

My goal, as always, is to make you a more fluent Python programmer. If you take this course, you will have made a major step forward on that journey.

As always, I offer discounts to students, pensioners, and people living outside of the 30 wealthiest countries in the world — just e-mail me to request an appropriate coupon code. There are also group discounts, if you want to buy five or more copies for your organization.

Click here to sign up for “Comprehending Comprehensions”!

Questions? Comments? Just leave a comment on this blog or send me e-mail; I’ll respond with an answer right away.

My new course, “Understanding and Mastering Git,” is now available

Ah, Git.  It’s one of the best and most important tools I use as a software developer.   Git is everything I want in a version-control system: It’s fast. It lets me collaborate. I can work without an Internet connection.  I can branch and merge easily, using a variety of techniques.  I can take a personal project and turn it into a large, collaborative one with minimal effort. And it’s cross platform, meaning that I know my clients and colleagues will be able to use it.

So, what’s the problem?  Git’s learning curve is extremely steep.  Until you understand what Git is doing, and how it works, you cannot use it effectively.  Moreover, until you understand what Git is doing, you will likely be puzzled and frustrated by its commands, messages, and documentation.

I’m thus delighted to unveil my latest online course: Understanding and mastering Git.  This course, which I have taught to numerous companies all around the world for more than a decade, includes:

  • Nearly 80 video lectures, for a total of more than 7 hours of videos (preview a number of videos here, on the course page)
  • Dozens of exercises, to help you practice and understand working with Git
  • 11 slide decks (in PDF format), the same ones I use when teaching.

If you have been frustrated by Git, or consider the commands you’ve been using to be a form of black magic, then this course is for you.  It walks you through Git’s commands, objects, and methods for collaboration.

This course has been battle-tested for a decade at some of the world’s best-known companies.  If you want to get the most out of Git, I’m sure that my course will help.  And if it doesn’t?  E-mail me, and I’ll give you a 100% refund.

Don’t let Git frustrate you any more.  Understand it.  Master it.  Tame it.   Learn from my “Understanding and mastering Git” course, today:

http://store.lerner.co.il/understanding-and-mastering-git

Not sure if this course is for you?  That’s fine: You can preview a number of the course videos for free from the course sales page.

Also: If you’re a student or pensioner, then you qualify for a discount on the course.  Just e-mail me, and I’ll send you a special discount code.

And finally: If you live in a country outside of the top 30 per-capita GDP countries in the world, then e-mail me and I’ll send you a special discount code to make the course more affordable to you.

You can and should learn Git, and I want to help you to learn it.  Try my course, and discover why so many software engineers won’t even think about using something else.

Four ways to assign variables in Python

Within minutes of starting to learn Python, everyone learns how to define a variable. You can say:

x = 100

and voila!  Your You have created a variable “x”, and assigned the integer value 100 to it.  It couldn’t be simpler than that.

But guess what?  This isn’t the only way to define variables, let alone assign to them, in Python. And by understanding the other ways that we can define variables, and the nuances of the “simple” variable assignment that I described above, you can get a better appreciation for Python’s consistency, along with the idea that “everything is an object.”

If you like what I write here, you’ll probably also enjoy my free, weekly “Better developers” newsletter, read by more than 10,000 developers every Monday.  Subscribe by clicking here!

Method 1: Plain ol’ assignment

The first way to define a variable is with the assignment operator, =.  Once again, I can say

x = 100

and I have assigned to x. If x didn’t exist before, then it does now. If it did exist before, then x now points to a new and different object.

What if the new, different object is also of a new and different type? We don’t really care; the nature of a dynamic language is such that any variable can point to an object of any type. When we say “type(x)” in our code, we’re not really asking what type of object the variable “x” can hold; rather, we’re asking what type of variable “x” is pointing to right now.

One of the major misconceptions that I come across in my Python courses and newsletter is just how Pvaython allocates and stores data.  Many of my students come from a C or C++ background, and are thus used to the “box model” of variable assignment: When we declare the variable “x”, we have to declare it with a type.  The language then allocates enough memory to store that type, and gives that memory storage an alias, “x”.  When I say “x=100”, the language puts the value 100 inside of the box named “x”.  If the box isn’t big enough, bad news!

In Python, though, we don’t use the box model of variable assignment. Rather, we have the dictionary model of variable assignment: When we assign “x=100”, we’re creating (or updating) a key-value pair in a dictionary. The key’s name is “x”, and the value is 100, or anything else at all. Just as we don’t care what type of data is stored in a dictionary’s values, we also don’t care what type of value is stored inside of a Python variable’s value.

(I know, it’s a bit mind-bending to say that Python variables are stored in a dictionary, when dictionaries are themselves Python values, and are stored in Python variables. It’s turtles all the way down, as they say.)

Don’t believe me?  Just run the “globals” function in Python. You’ll get a dictionary back, in which the keys are all of the global variables you’ve defined, and the values are all of the values of those variables.  For example:

>>> x = 100

>>> y = [10, 20, 30]

>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'x': 100, 'y': [10, 20, 30]}

>>> x = 200

>>> y = {100, 200, 300}

>>> globals()

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'x': 200, 'y': {200, 100, 300}}

But wait, we can do even better:

>>> globals()['x'] = 300
>>> x
300
>>> globals()['y'] = {'a':1, 'b':2}
>>> y
{'a': 1, 'b': 2}

That’s right; the result of invoking “globals” is not only a dictionary showing us all of the global variables, but is something we can modify — and whose modifications not only reflect, but also affect, our global variables.

Now, you might be thinking, “But not all Python variables are globals.” That’s true; Python’s scoping rules describe four levels: Local, Enclosing, Global, and Builtins.  Normally, assignment creates/updates either a global variable or a local one.  How does Python know which one to use?

The answer is pretty simple, actually: When you assign inside of a function, you’re working with a local variable. When you assign outside of a function, you’re working with a global variable.  It’s pretty much as simple as that.  Sure, there are some exceptions, such as when you use the “global” or “nonlocal” keyword to force Python’s hand, and create/update a variable in a non-local scope when you’re within a function.   But the overwhelming majority of the time, you can assume that assignment within a function creates or updates a local variable, and outside of a function creates or updates a global variable.

Note that this means assignment inside of a “for” loop or “if” statement doesn’t create a local variable; it creates a global one.  It’s common for my students to believe that because they are inside of an indented block, the variable they are creating is not global.  Not true!

If you’re in a function and want to see the variables that have been created, you can use the “locals” function, which operates just like the “globals” function we looked at earlier.  Even better, you can use the “vars” function, which invokes “locals” inside of a function and “globals” outside of a function.

So the first type of variable assignment in Python is also the most common, and can be subdivided into two basic categories, local and global.

I should add that I’m only talking here about variable assignment, not attribute assignment. Attributes (i.e., anything that comes after a “.” character, as “b” in the expression “a.b”) are a totally different kettle of fish, and have their own rules and quirks.

Method 2: def

If you want to create a function in Python, you use the “def” keyword, as in:

>> def hello(name):
...     return f"Hello, {name}"    # I love f-strings!

While we often think that “def” simply defines a function, I think it’s easier to think of “def” as actually doing two things:

  • Creating a new function object
  • Assigning that function object to the name immediately following the “def”

Thinking about “def” this way, as object creation + assignment, makes it easier to understand a variety of different situations that Python developers encounter.

First of all, “def” defines variables in the same scope as a simple variable assignment would. So if you’re in the global scope, you’re creating a global variable. Remember that Python doesn’t have separate namespaces for data and functions. This means that if you’re not careful, you can accidentally destroy your function or variable definition:

>> x = 100

>>> def x():
...     return "Hello!"

>>> print(x*2)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'function' and 'int'

Also:

> def x():
... return "Hello!"

>>> x = 100

>>> print(x())
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

In both of these cases, the programmer assumed that setting a variable and defining a function wouldn’t interfere with one another, with clearly disastrous results.

The fact that “def” assigns to a variable also explains why you cannot define a function multiple times in Python, each with its own function signature (i.e., argument count and types). Some people, for example, expect to be able to do the following:

>> def hello(name):
...     return f"Hello, {name}"

>>> def hello(first, last):
...     return f"Hello, {first} {last}"

They then assume that we can invoke “hello” with either one argument (and invoke the first version) or two arguments (and invoke the second).  However, this isn’t true; the fact that “def” defines a variable means that the second “def” obliterates whatever you did with the first.  Consider this code, in which I define “x” twice in a row with two different values:

>>> x = 100
>>> x = 200

You cannot realistically think that Python will know which “x” to choose according to context, right?  In the same way, Python cannot choose a function definition for you.  It looks up the function’s name in “globals()”, gets the function object from that dictionary, and then invokes it (thanks to the parentheses).

A final aspect of seeing “def” as variable assignment has to do with inner functions — that is, functions defined within other functions.  For example:

>> def foo():
...    def bar():
...        print("I'm in bar!")
...    return bar

What’s happening here?  Well, let’s assume that we execute function “foo”.    Now we’re inside of a function, which means that every time we define a variable, it’ll be a local variable, rather than a global one. The next thing we hit is “def”, which defines a variable.  Well, that means “bar” is a local variable inside of the “foo” function.

Then, in the next line of “foo”, after defining “bar”, we return a local variable to whoever called “foo”.  We can return any kind of local variable we like from a function; in this particular case, though, we’re returning a function object.

This just scratches the surface of inner functions, but the logic — we’re defining and then returning a local variable in “foo” — is consistent, and should make more sense if you think of “def” as just assigning variables.

Method 3: import

One of the most powerful aspects of Python is its very mature standard library. When you download and install Python, you have hundreds (thousands?) of modules available to you and your programs, just by using the “import” statement.

Well, guess what? “import” is defining a variable, too. Indeed, it often helps to think about “import” as defining a single variable, namely the one whose name you give when you invoke it.  For example:

>> import os

When I invoke the above, I am doing three things:

  • Python finds the module file os.py (or some variation thereof) and executes it
  • Python defines the variable “os” in the current scope
  • All of the global variables defined in the module are turned into attributes on the “os” variable.

It’s pretty easy to see that “import” defines a variable:

>> type(os)
<class 'module'>

What’s a bit harder to understand is the idea that the global variables defined inside of our module all become attributes on the module object. For example, in “os.py”, there is a top-level definition of the “walk” function. Inside of the module, it’s a global variable (function).  But to whoever imports “os”, “walk” isn’t a variable.  Rather, it’s an attribute, “os.walk”.  That’s why if we want to invoke it, we need to use the complete name, “os.walk”.

That’s fine, and works pretty well overall. But if you’re going to be using “os.walk” a lot, then you might not want the overhead of saying “os.walk” each and every time. Instead, you might want to create a global variable whose value is the same as “os.walk”.  You might even say something like this:

walk = os.walk

Since we’re assigning a variable, and since we’re not inside of a function, we’re creating a global variable here.  And since “os.walk” is already defined, we’re simply adding a new reference (name) to “os.walk”.

A faster, easier, and more Pythonic way to do this is with:

from os import walk

Although to be honest, this isn’t quite the same as what I did before. That’s because “from os import walk” does find the “os.py” module file, and does execute its contents — but it doesn’t define “os” as a variable in our global namespace.  Rather, it only creates “walk” as a variable, pointing to the value of what the module knows as “os.walk”.

Does that mean that “from … import …” doesn’t actually load the module? That would be pretty silly, in that future imports of “os” would then be less effective and efficient.

Python is actually pretty clever in this case: When it executes the module file, it creates the module object in sys.modules — a dictionary whose keys are the names of the modules we have loaded.  That’s how “import” knows to import a file only once; it can run “in” on sys.modules, check to see if a module has already been loaded, and only actually import it if the module is missing from that dict.

What if the module has been loaded?  Then “import” still defines the variable in the current namespace.  Thus, if your project has “import os” in 10 different files, then only the first invocation of “import os” actually loads “os.py”.  The nine following times, you just get a variable definition that points to the module object.

In the case of “from-import”, the same thing happens, except that instead of assigning the module’s name as a variable in the current namespace, you get the name(s) you explicitly asked for.

In theory, you can use “import” and “from-import” inside of a function, in which case you’ll define a local variable.  I’m sure that there is some use for doing so, but I can’t think of what it would be.  However, here Python is also remarkably consistent, allowing you to do things that wouldn’t necessarily be useful.

In Python 2.7, there were two different implementations of the “pickle” module, one written in Python (“pickle”) and one written in C (“cPickle”).  The latter executed much faster, but wasn’t available on all platforms.  It was often recommended that programmers do this, to get the best possible version:

try:
    import cPickle as pickle
except ImportError:
    import pickle

>>> pickle
<module 'cPickle' from '/usr/local/Cellar/python@2/2.7.14_3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/cPickle.so'>

This technique (which isn’t necessary with Python 3) only worked because “import” is executed at runtime, along with other Python code, and because “import” defines a variable.  What the above code basically says is, “Try to load cPickle but if you succeed, use the name pickle.   If you can’t do that, then just use the regular ol’ pickle library.”

Method 4: class

The fourth and final way to define a variable in Python is with the “class” statement, which we use to create (big surprise) classes.  We can create a class as follows:

class Foo(object):
    def __init__(self, x):
        self.x = x

Newcomers to Python often think of classes as blueprints, or plans, or descriptions, of the objects that will be created. But they aren’t that at all — classes in Python are objects, just like anything else.  And since they’re objects, they have both a type (which we can see with the “type” function) and attributes (which we can see with the “dir” function):

>> type(Foo)
<class 'type'>

>>> dir(Foo)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

The “class” keyword defines a new variable — Foo, in this case — which is assigned to a class object. A class object is just like everything else, except that it is callable, meaning that we can execute it (with parentheses) and get a new object back:

>> Foo(10)
<__main__.Foo object at 0x10da5fc18>

Defining a class means that we’re defining a variable — which means that if we have a previous class of the same name, we’re going to overwrite it, just as was the case with functions.

Class objects, like nearly all objects in Python, can have attributes added to them at runtime.  We can thus say:

>> Foo.abc = 100

And now I’ve added the “abc” attribute to the “Foo” object, which is a class.  I can also do that inside of a class definition:

>>> class Foo(object):
...     abc = 100
...     def __init__(self, x):
...         self.x = x

>>> Foo.abc
100

How is this possible?  Haven’t we, in our class definition, created a variable “abc”?  Nope — it looks like a variable, but it’s actually an attribute on the “Foo” class.  And it must be an attribute, not only because we can retrieve it with “Foo.abc” later, but because all assignments inside of a class definition aren’t creating variables, but rather attributes.  Inside of “class Foo”, we’re thus creating two attributes on the class — not only “abc”, but also “__init__”, the method.

Does this seem familiar, the idea global variables we define in one context are seen as attributes in another context?  Yes, that’s right — we saw the same thing with modules.  Global variables defined in a module are seen, once the module is imported, as attributes on that module.

You can thus think of classes, in some ways, as modules that don’t require a separate file. There are other issues as well, such as the difference between methods and functions — but in general, understanding that whatever you do inside of a class definition is treated as a  module can help to improve your understanding.

I don’t do this very often, but what does it mean, then, if I define a class within another class?  In some languages, such “inner classes” are private, and only available for use within the outer class. Not so in Python; since “class” defines a variable and any variable assignments within a class actually create attributes, an inner class is available to us via the outer class’s attribute:

>>> class Foo(object):
...     def __init__(self, x):
...         self.x = x
...     class Bar(object):
...         def __init__(self, y):
...             self.y = y
...
>>> b = Foo.Bar(20)
>>> b.y
20

Variables in Python aren’t just for storing data; they store our functions, modules, and classes, as well.  Understanding how various keywords define and update these variables can really help to understand what Python code is doing — and also provides for some cool tricks you can use in your own code.

If you liked what I wrote here, you’ll probably also enjoy my free, weekly “Better developers” newsletter, read by more than 10,000 developers every Monday.  Subscribe by clicking here.

Using Python to delete files based on other files’ names

I recently asked subscribers to my free, weekly “better developers” newsletter to send me their Python programming questions, promising that (a) I’d try to solve them, and publish the result to YouTube, and (b) anyone who submitted a problem that I selected would then get a coupon for 30% off of any of my books or courses.

Reader Harry submitted a great question about filenames, which I solve below. Thanks, Harry!

 

Less content + more exercises = better learning + more satisfaction. That’s Weekly Python Exercise.

I’ve been training people in programming, including in Python, for 20 years. I’ve always enjoyed teaching; it’s an amazing feeling to know that you’re helping people to accomplish things that they couldn’t do before. The fact that I get to travel the world, meeting so many smart and interesting people, and helping them to use Python in new and better ways, is a great part of what I do.

My courses are constantly undergoing improvement and evolution. If you took a course with me last year, the odds are pretty good that I’ve tweaked it in a number of ways — improving the explanations, changing the demos, and streamlining the exercises.

One change that people don’t expect me to make, but which I do every year, is to remove content. That’s right; every year, I cover less material in each of my courses than I did the previous year.

Why would I do that? How can that possibly help?

Because by covering less material, I can give my students more time to truly learn the topics that remain. And when I say “truly learn,” I mean that we not only have more opportunity for questions and discussion, but also for exercises. Many, many exercises.

I find that removing content and adding exercises helps people to learn better. It helps the information to settle into their minds more firmly. It helps the students to truly, deeply understand the points I’m trying to make. And the point of a course isn’t to race through a checklist of topics, being able to say, “I covered them all!” Rather, it’s ensuring that people have learned the most important ideas, so that they can progress on their own. Having 100 topics on your day-long syllabus isn’t really going to help anyone; no human can remember that much.

I also encourage my students to work in pairs when they’re solving exercises. Without fail, those who follow my instructions, and work together with others to solve the problems, learn more and have a deeper understanding of what we’ve done.

About a year ago, I had a thought experiment: What if I were to make a course that was only exercises? That is, I wouldn’t do any teaching up front. Rather, the learning would take place in the exercise, in the collaborative solving of the exercise, and in the follow-up afterwards, including when I solve the problem.

Thus was born Weekly Python Exercise. My goal is to make you a more fluent Python developer, and Weekly Python Exercise represents the best combination of content, exercises, and technologies for accomplishing this task. The first cohort of WPE has been learning since June, and the feedback has largely been very positive. But there’s always room to improve, and so in creating this new, January 2018 cohort, I thought long and hard about how to increase interactions and make it as valuable as possible — within the constraints of online teaching and short, weekly exercises.

I’m very proud of WPE, and I’m excited that dozens of people are going to be joining me for this improved version of Weekly Python Exercise. I can’t think of a better way to help boost your Python career.

What does a $180 subscription to Weekly Python Exercise get you?

  • 52 exercises
  • 52 detailed (written) answers
  • Access to our exclusive forum, in which you can chat with other WPE’ers
  • Access to exclusive office hours with me, to discuss the problems

Also: If you sign up now, you get free, unlimited access to future cohorts of Weekly Python Exercise. You’ll be invited to join the forums and office hours, and to solve the problems along with everyone else, whenever I next offer this course.

And if it’s not for you? Just let me know, and I’ll refund your money. But I think that you’re going to really love it, and get a lot out of it. You’ll understand how Python works behind the scenes

In 48 hours, this opportunity will go away until I next offer WPE — and I’m not sure when that’ll be. So don’t delay; sign up for Weekly Python Exercise.

Yes, sign me up for Weekly Python Exercise!

Questions or comments?  Just watch this video:

Registration closes soon for Weekly Python Exercise

Weekly Python Exercise logoWeekly Python Exercise” starts on January 2nd, and is designed to help intermediate Python developers level up their coding skills.  But registration ends on December 20th!  What does the course include, how does it work, and what do you get for $180?  I explain it all in this video…

More than 20 years of programming in Python, and more than 20 years of teaching Python (and other languages) at companies around the world, have gone into this course.  If you want to become a more fluent Python programmer, I’m positive that this course will help.

Not sure?  Have questions? Just e-mail me.  But don’t wait too long…

Focus on the process: Your Python questions, answered

Weekly Python Exercise logoA few weeks ago, I asked subscribers to my free, weekly “Better developers” list to send me their Python problems.  I got about 20 responses from around the world, some more complex than others.  I promised to answer some of them in video.

Why? Because becoming an expert Python developer means understanding, in a deep way, how Python works. The stronger your mental model of Python’s innards, the better you can use the language to solve problems.  And watching someone solve problems, or work their way through problems in real life, helps to develop and improve those mental models.

A large proportion of my teaching takes place via exercises. (And in the case of Weekly Python Exercise, it’s the overwhelming majority of the teaching, as the name implies.) But as important as it is for my students to work through the exercises, it’s also important that I walk them through the process I use when solving the exercise. Learning the correct process is more important than getting the answer right to a specific problem, because once you start thinking in the right way, with an improved mental model, you’ll be able to solve new and different problems.

I’m trying something similar here: People ask questions, and I try to answer them. Sometimes, I’ll hit a brick wall, or an unexpected detour, or I’ll just be surprised. Guess what? This happens to all of us, and it’s part of the process of solving problems. But it’s also part of the fun and excitement of development.

With that in mind, I present the first two problems/questions that my readers submitted:

If you like these questions and walkthroughs, then you’ll love Weekly Python Exercise, starting on January 2nd, a year-long course for intermediate Python developers.

And if you have Python questions you’d like me to answer, join my list and ask away!  If I choose your question, I’ll give you a coupon for 30% off any of my books or courses.

Registration is open for the January 2018 cohort of “Weekly Python Exercise”

Weekly Python Exercise logoWhen I started to program in Python more than 20 years ago, there weren’t a lot of resources out there. Sure, there were a handful of books, and a few Web sites, and (of course) forums and mailing lists. But that was about it.

Nowadays, Python is white-hot, with companies, universities, and individuals learning the language. Whether you’re a data scientist, Web developer, system administrator, test author, or hobbyist, you’re probably learning Python. Not surprisingly, there are oodles of books, courses, and resources for people learning the language.

And then? Well, then you’re on your own.

The problem is that there aren’t a lot of resources for intermediate-level Python developers to improve their fluency with the language. Sure, you can read through Stack Overflow and Reddit, as well as read blogs and watch conference videos. But given how much is out there for beginners, you would think that there would be something to help people who have already taken a Python course, and who are ready for the next stage.

The good news: I’m here to help.

More specifically: My course, Weekly Python Exercise, is just what the doctor ordered. WPE makes you a more fluent, more knowledgeable Python developer by forcing you to learn and practice your skills every week.

Every Tuesday, you’ll receive a new Python programming challenge. These challenges are designed to be relatively short and small, taking less than an hour of your time. The following Monday, you’ll receive my suggested answer, along with a description of why I chose to solve the problem in the way I did.

Along the way, you’ll learn about — or improve your understanding of — such topics as:

  • nested functions
  • iterators
  • generators
  • decorators
  • object inheritance
  • properties
  • threads and processes
  • the “logging” module
  • the “pickle” module

Most importantly, you’ll be solving these problems along with other developers from around the world. You’ll be able to participate in a forum, in which you can discuss possible solutions. Such interactions are the key to effective, deep learning, and I’m going to do my best to encourage active participation and discussion in our forum.

Moreover, I’ll offer live, online office hours every few weeks. This will give you a chance to ask me about the exercise questions, as well as the solutions. It’s your chance to discuss the exercises in greater depth.

I’m also going to include several multi-week projects, in which successive exercises build on previous ones. This will allow us to build larger projects, while remaining within the constraints of simple, weekly exercises.

This is the second time I’m offering Weekly Python Exercise. I’ve incorporated many suggestions I received from the first set of participants, making this the best way I can think of to improve your Python skills. I’ve improved the exercises, improved the social interactions, and made myself more available to discuss the questions (and answers) with all of the participants.

If you have a good knowledge of Python but want to make it even better, then Weekly Python Exercise is for you. But — and here’s the most important thing — the next cohort will be starting on January 2nd. After that, registration for WPE will be closed.

If you want to level up your Python, now is the time to sign up. I’m not sure when I’m next going to offer WPE, which means that once the course starts, you won’t be able to join.

If you have read a Python book, or taken a Python class, and want to know how to really “get” Python, look no further: Weekly Python Exercise is coming.

Click here to register for the January 2018 cohort of Weekly Python Exercise.

Wondering if WPE is for you? Contact me at reuven@lerner.co.il., and I’ll personally read (and respond to) your question.

If you’re on the fence, and want to sample WPE, you can just enter your e-mail address below, and receive (free of charge) two exercises from the most recent cohort: