Object Oriented Python
Intro
Python is a strange language. You can do a lot with it, up to and including shooting your own foot off.
Python allows
- array splicing
>>> =
>>>
>>>
>>>
- appending lists with the '+' operator
>>> +
- using the first string of a progam as documentation
)
- renaming objects as they are imported
>>>
>>>
< = = =>
>>>
- modifying the type of a variable at runtime
>>>
>>> = 2
>>> =
>>> =
>>>
< = = =>
- within a function, using a variable that has not yet been declared
>>> :
... global
... += 2
...
>>> = 0
>>> ;
2
Python disallows
- declaring types
>>> = 2
1
, = 2
^
:
- throwing errors before runtime
>>> :
... += 2
...
>>>
:
1, in <>
, 2, in
, :
- declaring and assigning a global variable in the same statement
>>> :
... global = 1
2
, global = 1
^
:
- bad indentation
>>>
...
2
,
^
:
In this article, I go over some of the things you can do with object-oriented python, some things you should do, and some you really shouldn't.
Objects in python
In other object-oriented languages I am familiar with, notably Java,
each object has its own methods you must learn to use.
size
, length
, and length()
,
for example, are easily confused even for experienced developers.
In python, there is only one function, and it is not a property of the object.
>>>
3
Similarly, all array-like objects can be treated as arrays:
>>>
How is this done?
In Java, C++, and every other language I can think of,
objects are essentially implemented as very complicated structs:
there are pointers to data and void pointers to functions.
All object pointers are void pointers at runtime;
this is safe because types are checked at compile time.
How would you implement a global type-independent length
function
when you don't know what length means for that object?
The closest you could get is a wrapper:
public static int
It's a nightmare just to write 3 of those switch cases;
imagine how awful it would be for every object in java.util
.
Well, it turns out, that wrapper is essentially what python does.
When you run len(object)
, all it does is return object.__len__()
!
It's the same for every other attribute -
accessing an item, iterating, the whole
shebang.
>>> :
... :
... return 4 # guarenteed by IEEE to be random
... :
... return 3
... :
... yield 1
...
>>> =
>>>
4
>>>
3
>>>
...
...
1
We have to yield
1 instead of return
because iter
takes a
generator.
Using objects
So, now we know how objects work - all we have to do is implement the builtin methods. How do you extend a class, though? Java's entire paradigm is built around inheritance.
You extend classes in Python by passing them to the constructor:
>>> :
... :
...
...
>>>
>>>
>>>
1
>>>
!
And what's up with that pesky self
, anyway?
>>> :
... :
...
... :
...
...
>>> =
>>>
:
1, in <>
, : 0 1
>>>
!
It turns out that Python automatically passes self
to each method when it's called.
The reason for this is one of my least favorite parts of Python:
there's no class namespace. If you want to refer to an attribute of the instance,
you have to use self
.
>>> :
... :
... = 3
... :
...
... :
...
...
>>> =
>>>
3
>>>
:
1, in <>
, 5, in
, : is not
>>>
3
Constructors and Destructors
So . . . about those.
When you instantiate an object in python, it calls
__new__
then __init__
, in that order.
__init__
is None
by default; __new__
may or may not be.
It's considered bad practice to define __new__
in your program.
When an object is destroyed through garbage collection,
__del__
is called.
This sounds simple enough so far.
If __init__
is interrupted, __del__
may or may not be called.
If you use a with
statement, i.e. with open(filename) as f:
,
neither __init__
nor __del__
are called; __enter__
and __exit__
are called instead.
I'm still confused by these.
Conclusion
While python certainly supports objects, I think it is harder to create objects in python than in other languages, especially compared to the simplicity of the rest of the language. You shouldn't have to know how the garbage collector handles references to create a deconstructor (I haven't seen any syntax for deconstructors I liked, but that's a different topic). You especially should not have to create methods with two underscores before and afterwards to have a useful class.
</rant>
Example
I'll leave you with an example from my research project:
= 3286
=
=
= //
return
=
=
return ,
return