
A Guide to Python's Magic Methods (2012) - apsec112
https://rszalski.github.io/magicmethods/
======
montecarl
This part is a little dated (it is a 2012 post after all):
[https://rszalski.github.io/magicmethods/#comparisons](https://rszalski.github.io/magicmethods/#comparisons)

In Python 3 __cmp__ is ignored and you have to use the other methods. To make
this easier, you can use
[https://docs.python.org/3/library/functools.html#functools.t...](https://docs.python.org/3/library/functools.html#functools.total_ordering)

~~~
opencl
It's amazing that Python 3 was 4 years old when this post was made and yet
saying "Python" was still implicitly assumed by basically everyone to mean
2.x.

~~~
kjeetgill
Is it that amazing? I don't think I've had use 3 until this year and I still
have to flip-flop.

AND I say this as someone who was reading peps going into 3's release.

Do Ubuntu or Fedora default to python 3 yet? Arch? My RHEL experience isn't as
representative.

~~~
bhrgunatha
Arch's default is Python 3, but there are still many official Python 2
packages, mostly in community i.e. adopted from the AUR:

Core: 1

Extra: 96

Community: 822

AUR: Over 2300 depending on how you search

~~~
lathiat
The official python recommendation is not to "default" the 'python' command as
python3, and they should just explicitly be 'python' and 'python3'

This is what every distro except arch does (for whatever reason)

[https://www.python.org/dev/peps/pep-0394/](https://www.python.org/dev/peps/pep-0394/)

~~~
mkesper
But that should turn around NOW, comsidering 2020 will be EOL for Python2
(except for Redhat which will have to ride that dead horse for years to come).

~~~
cferr
RHEL 8 will ship with Python 3 as the default.

[https://access.redhat.com/documentation/en-
us/red_hat_enterp...](https://access.redhat.com/documentation/en-
us/red_hat_enterprise_linux/7/html/7.5_release_notes/chap-
red_hat_enterprise_linux-7.5_release_notes-deprecated_functionality)

------
kqr
This is a great explanation and a must-read for Python developers. Once you
know this stuff, you'll be a much stronger debugger.

But it's also worth throwing a warning out there: when you first learn about a
new type of magic, you'll be tempted to use it everywhere. Be careful!

I can recognise a clear specific period in my Python work which was just after
I had read this, and a bunch of things suddenly became implicit.

~~~
nomel
> Once you know this stuff, you'll be a much stronger debugger.

As you suggest, more accurately, you'll require the next person who debugs
your code to read this, making them much better at debugging your code.

I no longer use magic and completely avoid meta programming in python. It
confuses everyone, is not needed (just use a boring factory function), and
severely limits who can help you work on your code, for what? A few lines of
less boilerplate here and there? "Succinctness"? Some sort of "elegance"? More
likely, a DSL that nobody understands but you!

The more I write, and mostly the more I interact with other people, the more I
realize that code _needs_ to be boring. No magic. I think this is why go is
succeeding: no magic.

~~~
rootusrootus
100% agree. I figure this is a big part of what turns normal developers into
senior developers, and lead developers. It's easy to code. What takes wisdom
is 1) knowing what not to write, and 2) self control on how you write it. As a
mentor I try to convey this to the fresh new supercoders joining our team.

------
florabuzzword
Wonderful. I’ve never seen this resource before.

A related article I got a lot out of was ‘Understanding Python Metaclasses’,
an in-depth breakdown of Python class instantiation. Here’s the link to that:

[https://blog.ionelmc.ro/2015/02/09/understanding-python-
meta...](https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/)

------
pypypypypypy
It's awesome that someone has taken the time to write this all up. With
reference to this section
([https://rszalski.github.io/magicmethods/#descriptor](https://rszalski.github.io/magicmethods/#descriptor))
the author mentions that descriptors are "meant to be held by an owner class."
which is true, however in their example, they are storing the value as
`self.value` on the descriptor object itself meaning that if the user were to
have two instances of `Distance` all their values would be the same for meter
or foot on all instances of `Distance`. One way to solve this is to store the
values in a dictionary-like structure on the descriptor, e.g.
`self.data[instance] = your_stored_value`.

------
devxpy
It is when you get to this part of python, that you achieve true Nirvana.

It's absolutely bonkers the extent to which you can be dynamic in this
language.

It's the very reason why Django is so DRY.

~~~
Waterluvian
Django's DRY suuuuuuuucks when you're getting started. It's basically all this
magic that you can't understand without already knowing Django.

Why does get_attr get called? Oh because it begins with the word "get" and
there's an attribute that defines a method field called "attr".

I use Django a lot and generally it's great. But I hate that you can't follow
your code paths from start to finish on the surface. You have to know about
how it works underneath. Meaning you can't just be a python + web server
expert. You have to also be a Django expert. So I get non-Django experts
reviewing code and they have no clue why things work or break.

Just an opinion. Not saying this is objectively wrong.

~~~
sbjs
People who feel this way usually use Flask instead. Worth checking out.

[http://flask.pocoo.org/](http://flask.pocoo.org/)

~~~
Waterluvian
Flask is great for smaller things where Django is far too verbose. Like single
file webservers for basic stuff.

Its also for more complex stuff but then you have to grab additional libraries
to do stuff like db management, migrations, serialization, etc.

Flask also has some, in my opinion, rather uncomfortablly unintuitive global
scope stuff. Where responses aren't passed into the view function, they're
available on the imported flask object.

~~~
sbjs
Good to know. I haven't used Flask recently, I have used Express.js which is
Node.js's version of Flask, and I really like how simple it is. Most apps
these days seem to have a REST (or GraphQL) backend and dynamic (often
React.js) frontend. Flask (and Flask-RESTful) would probably be a better fit
for this type of app than Django.

~~~
Waterluvian
Yeah don't let me dissuade you. Flask is a prime piece of software.

------
olooney
Be sure to read "Appendix 2: Changes in Python 3" at the very end of the
document! I was preparing a long "Actually..." rant before I saw that.

------
saagarjha
> Be careful, however, as there is no guarantee that __del__ will be executed
> if the object is still alive when the interpreter exits, so __del__ can't
> serve as a replacement for good coding practices (like always closing a
> connection when you're done with it.

When the interpreter exits, your program's resources should be reclaimed by
the operating system, right? So why not just use __del__?

~~~
gvx
You almost always only want to implement __del__ if you're writing an
extension in C. Otherwise, the GC generally takes care of cleanup perfectly
fine.

And in cases like the one cjhanks describes, __del__ doesn't get called
reliably enough. In those cases, using a contextmanager is better.

------
jl2718
This is a godsend. Thank you. Without this, I’d nearly given up on python
already, but, wow, thank you.

~~~
deathanatos
While there's no harm in having a second guide, I just want to make sure folks
do know this is in the official documentation:
[https://docs.python.org/3/reference/datamodel.html](https://docs.python.org/3/reference/datamodel.html)

(The article will perhaps be a better guide to those newer; the data model
page is … pretty dense.)

Also, I find is exceptionally handy to have a Chrome "search engine" for the
Python docs while I work. That is, on chrome://settings/searchEngines I have
added a custom search engine with this setup:

    
    
      Search Engine: Python Docs
      Keyword: py
      URL: https://google.com/search?q=site:https://docs.python.org/3+%s&btnI
    

(The URL is an "I'm feeling lucky" search on Google, limited to the Python 3
docs. Note that it is set to search Python 3.)

This allows me to type, e.g.,

    
    
      py data model
    

in the URL and get the above page. Want the asyncio module docs?

    
    
      py asyncio
    
    

(I similarly have "mdn" for the developer.mozilla.org docs, which are also
excellent.)

------
meowface
Good guide, but missing Python 3's __next__.

