layout: post title: "Python Concepts: Part None" date: 2014-09-20 17:30:00 +0100 comments: true
Let's learn about nothing. More particularly, let's learnt about python's concept of representing nothing, None. This is the most nothingest concept of nothing as well - for example, zero is nothing, but it's also a number, so it still has some information. Other names for nothing from other programming languages include null, nil, or Nothing.
I'm writing this post in IPython. If you want to follow along at home, get your IPython console started by typing ipython at the command prompt. Didn't work? Install it. Bam.
Now, let's start. Let's see what happens if ask for nothing:
In [1]:
None
No output - makes sense. Let's try outputting it to screen though:
In [2]:
print None
Aha, we get some output. print turns its input into a string so it can be output - and the string output of None is 'None'. Let's check that string representation:
In [3]:
str(None)
Out[3]:
Now, since we didn't use print, the output comes from the IPython prompt, with an "Out" marker to indicate that. IPython takes the expression you typed in, evaluates it, and displays the result as a prompt - unless the result is None, when it displays nothing! And you guessed it, input 1 evaluated to None, and so did input 2 (print actually can't even return anything).
So if we print again, there is no output prompt, since the print statement evaluates to nothing. Let's try printing the string of None:
In [4]:
print str(None)
Brilliant.
Anyway, the string "None" is something, and we're here to investigate nothing. Let's use an IPython feature to find out more about it:
In [5]:
None?
{% highlight ipy %}
Type: NoneType
String form: None
Namespace: Python builtin
Docstring:
Intriguing. None has a type - the NoneType. In fact, every object in python has a type, which is like a class in other languages, except it extends to builtin things as well.
The String Form there - that's what you get when you pass None to str as we've seen.
Namespace is 'Python builtin' - which means, surprise surprise, it's built-in to Python.
There's no docstring - this is a way of adding documentation to objects in Python for users to access. Let's check for a docstring on another object we know about:
In [6]:
str?
{% highlight ipy %} Type: type String form: <type 'str'> Namespace: Python builtin Docstring: str(object='') -> string
Return a nice string representation of the object. If the argument is a string, the return value is the same object. {% endhighlight %}
Ah, str's docstring is much more instructive - and it tells us how to do what we did on line 3!
But its type is type? This means we can make fresh str objects by calling the type:
In [7]:
str()
Out[7]:
And tada, a blank string appears.
Can we do that with the NoneType I wonder?
In [8]:
NoneType()
Uh-oh. Looks like we don't actually have NoneType available in our current namespace - just None. But luckily, we can ask for the type of None, store it in a variable, and call that:
In [9]:
type(None)
Out[9]:
In [10]:
local_none_type = type(None)
In [11]:
local_none_type()
Dang. We can have a handle on the NoneType type, but we can't make any more of it. This is actually a special rule for the NoneType... Does it mean there is only ever one None?
In [12]:
a = None
In [13]:
b = None
In [14]:
a == b
Out[14]:
Well, they're equal, that's a start. But can we check that a and b are exactly the same thing?
In [15]:
a is b
Out[15]:
Yes indeed they are. So there is only ever one None, and we can never make any more of it. That's useful to know - write it down in your copy book now.
Let's have a break with a quote on nothing:
Nothing proceeds from nothingness, as also nothing passes away into non-existence.
-- Marcus Aurelius, Meditations, IV, 4
Let's continue; I wonder if None can be checked against:
In [16]:
if None: print "Yes, none."
Oh, nothing happened. Let's see what happens if we go the other way:
In [17]:
if not None: print "Yes, not none."
Aha! So None is never True, and always False? Let's just check that by turning it into a boolean:
In [18]:
bool(None)
Out[18]:
Exactly.
That explains why our if statement worked that way - None gets turned into False when we test it as a boolean.
Let's try doing some more day-to-day things with None.
In [19]:
None + None
In [20]:
None - None
In [21]:
None + 0
So, you can't really do anything. Makes sense that you do (nearly) nothing with nothing.
Let's check its directory of methods though - maybe it has something it hasn't told us yet.
In [22]:
dir(None)
Out[22]:
Wow, that's a lot of things! How many things?
In [23]:
len(dir(None))
Out[23]:
Wow, there are actually 15 things that None can do!?
Let's try from the top...
In [24]:
None.__class__
Out[24]:
NoneType again? I thought we already got that guy with type! Is that the same NoneType really?
In [25]:
type(None) is None.__class__
Out[25]:
Okay, that's boring - just another way to get ahold of that __class__ it looks like.
Let's check the next one - __delattr__.
In [26]:
None.__delattr__
Out[26]:
Okay, it's a method-wrapper. Guess that means it's like a method. Let's try calling it.
In [27]:
None.__delattr__()
Okay, you want an argument? I'll give you an argument!
In [28]:
None.__delattr__("argument")
Oh, you want an argument that's the name of an attribute? Why didn't you say? We already know the name of an attribute that we don't need - __class__ is something we can get by calling type - so let's try saving some space by getting rid of that:
In [29]:
None.__delattr__("__class__")
Well that's annoying, but I guess it's okay for python to have some protection over such built-in features. For all we know, type might need the __class__ attribute to be there to work, right?
I give up, let's try the next one.
In [30]:
None.__doc__
Oh great, nothing. This is actually the attribute that stores an object's docstring though - and as we saw earlier, None has no docstring.
Let's check by getting the str docstring in the same way:
In [31]:
str.__doc__
Out[31]:
Yup, that's the string, although the new-line characters have been displayed as \\n. Next!
In [32]:
None.__format__
Out[32]:
In [33]:
None.__format__()
In [34]:
None.__format__(None)
Okay, let's pass in an empty str.
In [35]:
None.__format__("")
Out[35]:
In [36]:
None.__getattribute__()
Let's try giving it the name of an attribute...
In [37]:
None.__getattribute__("__class__")
Out[37]:
Wow, we just discovered that the 'dot' operator really just calls the __getattribute__ method of the object! So you can get any attribute that way? Let's try getting them all!
In [38]:
for name in dir(None):
print name, " -> ", None.__getattribute__(name)
Wow, that saved some work, checking what they are and where they are from! Most seem to be part of the NoneType object, but some are from object or type. Weird!
Wait, is None an object ?
In [39]:
isinstance(None, object)
Out[39]:
Apparently so! What else is an object?
In [40]:
isinstance(object, object)
Out[40]:
In [41]:
isinstance(type(None), object)
Out[41]:
In [42]:
isinstance(type, object)
Out[42]:
Well, I heard python is object-oriented, but it seems oriented towards making everything an object.
So what does that mean? Does object have some stuff on it that you can do anywhere or something?
In [43]:
dir(object)
Out[43]:
In [44]:
len(dir(object))
Out[44]:
Holy smokes, that's like the same list that None has! Wait, is it exactly the same list?
In [45]:
dir(object) == dir(None)
Out[45]:
Yes indeed! Aww wait, this means we learnt nothing interesting about None - it only has all the attributes that every other object has. So maybe it really doesn't do anything!
But we've learnt some valuable lessons:
NoneNone is NoneTypeNoneNone does nothing interestingNone into a string, it becomes 'None'. If you turn None into a boolean, it becomes False.That's all we have time for in this blog post! Next time: True and False enter the picture in full focus.