object to type relation

The classes object and type have unique relationship: object is an instance of type, and type is a subclass of object. This is magic.

== vs is

The == operator compares the values (uses __eq__() method) of objects (the data they hold), while is compares their identities.

Private attributes

Never, ever use two leading underscores. This is annoyingly private. If name clashes are a concern, use explicit name mangling insted (e.g, _MyThing_blahblah). This is essentially the same thing as double-underscore, only it's transparent where double underscore obscures.

__str__ vs __repr__

__repr__ returns a string representing the object sa the developer wants to see it.__str__ returns a string representing the object as the user wants to see it.

Magic methods

Why we use len(collection) instead of collection.length() or why we use a == b instead of a.is_equal(b)?

The answer is: following Python data model API allows your own objects play well with the most idiomatic language features.

Object model

object model is the properties of objects in general in a specific computer programming language.

Talking about len, it is not just a shortcut to sequence.__len__(), it can work even with objects without __len__ method (if the object is iterable, then len will try to count all items iterating throw them).

Another benefit of len is that you don't need to memorize which function name you used to return number of items: .length() or .size(). According to PEP-20: There should be one-- and preferably only one --obvious way to do it.

Key-only arguments in Python 3

To specify keyword-only arguments when defining a function, name them after the argument prefixed with *. If you don't wan't to support variable positional arguments but still want keyword-only arguments, put a * by itself in the signature:

No processing is done with the annotations. They are merely stored in the __annotations__ attribute of the function and have no meaning to the Python interpreter. Annotations may be used by tools such as IDEs, frameworks, and decorators.

Mutable types as parameter defaults

Modification in place

When we pass mutable object as argument to function where it would be modified. This type of functions must return None value (it makes clear to the caller that the object itself was changed, and no new object was created).

Closures

A closure is a function with an extended scope that encompasses nonglobal variables referenced in the body of the function but not defined there (can access nonglobal variables that are defined outside of its body).

A memoryview is essentially a generalized NumPy array structure in Python itself (without the math). It allows you to share memory between data-structures (things like PIL images, SQLite databases, NumPy arrays, etc.) without first copying. This is very important for large data sets.

Travis Oliphant

Dicts

Dicts are fast but have significant memory overhead (because of hash table usage). They provide fast access regardless of the size of the dictionary.

Modifying the contents of a dict while iterating through it is a bad idea. Python may decide to rebuild the hash table and so positions of elements in the table may be changed.

In Python 3, the .keys(), .items() and .values() methods return dictionary views, so they immediately reflect any changes to the dict.

Iterator vs iterable

Any object from which the iter built-in function can obtain an iterator is iterable. Objects implementing an __iter__ method returning an iterator are iterable. Sequences are always iterable; as are objects implementing a __getitem__ method that takes 0-based indexes.

Any object that implements the __next__ no-argument method that returns the next item in a series or raises StopIteration when there are no more items. Python iterators also implement the __iter__ method, so they are iterable as well.

Generator vs function

When we call a normal Python function, execution starts at function's first line and continues until a return statement, exception, or the end of the function (which is seen as an implicit return None) is encountered. Once a function returns control to its caller, that's it. Any work done by the function and stored in local variables is lost. A new call to the function creates everything from scratch.

This is all very standard when discussing functions (more generally referred to as subroutines) in computer programming. There are times, though, when it's beneficial to have the ability to create a "function" which, instead of simply returning a single value, is able to yield a series of values. To do so, such a function would need to be able to "save its work," so to speak.

I said, "yield a series of values" because our hypothetical function doesn't "return" in the normal sense. return implies that the function is returning control of execution to the point where the function was called. "Yield," however, implies that the transfer of control is temporary and voluntary, and our function expects to regain it in the future.

New in Python 3.5: async and await syntax

Since Python 3.5 native coroutines are their own completely distinct type, before they were just enhanced generators. async syntax makes coroutines a native Python language feature, and clearly separates them from generators.

functools.lru_cache

weekref

Objects are never explicitly destroyed; hower, when they become unreachable they may be garbage-collected.

"Data Model" chapter of The Python Language Reference

The weakref module allows the Python programmer to create weak references to objects.

A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. Commonly uses to implement caches.

abc

ABC uses to check if the object has an interface we need (for example, if it can behave like a dict or an iterable). We can check if the object has necessary attributes and so if it walks like a duck and swims like a duck and quacks like a duck, it must be a duck. Alternative way is to check if the object subclasses an ABC that describes necessary interface.

abc module contains decorators that can be used to define abstract methods (methods that must be present).

Descriptor

Descriptor is a class implementing one or more of the __get__, __set__ or __delete__ special methods and one of its instances is used as class attribute of another class, the managed class. Descriptors manage the access and deletion of a managed attributes in the managed class, often storing data in the managed instances.

Dunder-method

Methods like __eq__, __getitem__.
Also known as special or magic methods.

Magic

"Magic method" term was adopted from Ruby. Actually, these methods are opposite to magic, their behavior quite straightforward.

Functional language

Python is, by design, not a functional language - whatever that means. Python just borrows a few good ideas from functional languages.

Fluent Python by Luciano Ramalho

Future

Also known as promise.

An object which represents the result of a function call which is asynchronous.

GIL

GIL or Global Interpreter Lock is a mutex that prevents multiple native threads from executing Python bytecodes at once.

Jython and IronPython have no GIL. PyPy and CPython have a GIL.

GIL disadvantage: prevents multithreaded CPython programs from taking full advantage of multiprocessor systems in certain situations. There is no good enough GILless CPython implementation yet.

Concurrency: one of the most difficult topics in computer science (usually best avoided).

David Beazley

Hashable

An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() method). Hashable objects which compare equal must have the same hash value.

Hooks vs primitive operations

A hook is a method that can be defined in an abstract class and can be overridden in concrete classes. The difference between primitive operations and hooks is that hooks can be overridden by a derived class but is not obligated to do so, while a primitive operation must be implemented or NotImplementedError will be raised.