In [1]:
    
%%HTML
<style> 
div#notebook-container.container {
  /* This acts as a spacer between cells,
     that is outside the border */
  margin: 2px 0px 2px 0px;
  list-style: none;
  padding: 0;
  margin: 0;
  -ms-box-orient: horizontal;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -moz-flex;
  display: -webkit-flex;
  display: flex;  
  justify-content: space-around;
  -webkit-flex-wrap: wrap;
  flex-wrap: wrap;
  -webkit-flex-direction: row;
  flex-direction: row;
}
div.cell {
width:550px
}
  </style>
    
    
The code on the left is a hack to make this notebook two-column. I found it here:
http://stackoverflow.com/questions/23370670/ipython-notebook-put-code-cells-into-columns
Welcome to the OOP-session of our Python course! This notebook introduces Python's OOP-concepts in a two column-style side by side with an equivalent formulation in Java respectively.
We chose Java here, as it is a popular OOP-enabled language that many of you are probably familiar with. Also, we found it helpful to compare Python-style to some other language and Java-OOP is still somewhat easier to read than OOP in C-ish languages.
class SpaceShip(SpaceObject):
    bgColor = (0, 0, 0, 0)
    def __init__(color, position):
        super(SpaceShip, self).__init__(
                position)
        self.color = color
    def fly(self, moveVector):
        self.position += moveVector
    @staticmethod
    def get_bgColor():
        return SpaceShip.bgColor
See https://julien.danjou.info/blog/2013/guide-python-static-class-abstract-methods for a guide about the decorators @staticmethod, @classmethod and abstractmethod.
Classmethods have no equivalent in Java. They are like special static methods that get the class as their initial, implicit argument:
@classmethod
    def get_bgColor(cls):
        return cls.bgColor
public class SpaceShip extends SpaceObject {
    public static Color bgColor =
            new Color(0, 0, 0, 0);
    public Color color;
    public SpaceShip(Color col, Vec3D pos) {
        super(pos);
        color = col;
    }
    public void fly(Vec3D move) {
        position.add(move);
    }
    public static Color get_bgColor() {
        return bgColor;
    }
}
from abc import ABCMeta
class Target():
    __metaclass__ = ABCMeta
    @abstractmethod
    def hit(self, strength):
        pass
public interface Target {
  public void hit(double strength);
}
//or
public abstract class Target {
  public abstract void hit(double strength);
}
class SpaceShip(SpaceObject, Target):
    def hit(self, strength):
        print "Damn I'm hit."
public class SpaceShip extends SpaceObject 
    implements Target {
  public void hit(double strength) {
    System.out.println("Damn I'm hit.");
  }
}
class Hitpoints(Target):
    def __init__(self):
        self.hitpoints = 100
    def hit(self, strength):
        self.hitpoints -= strength
class SpaceShip(SpaceObject, Hitpoints):
    def __init__(self):
        Hitpoints.__init__(self)
        super(SpaceShip, self).__init__()
public class HitpointSpaceShip extends 
    SpaceShip implements Hitpoints {
  double hitpoints = 100.0;
}
public interface Hitpoints extends Target {
  //Java 8 introduced default-implementations:
  default void hit(double strength) {
    ((HitpointSpaceShip) this).hitpoints -=
        strength;
  }
}
class Fraction():
  def __init__(self, numerator,denominator):
    self.num = numerator
    self.den = denominator
  def __mul__(self, other):
    return Fraction(self.num * other.num,
        self.den * other.den)
Overview of magic methods:
Original essay about new-style classes by Guido van Rossum: https://www.python.org/download/releases/2.2.3/descrintro/
New-style class:
In [31]:
    
class classA():
    pass
a = classA()
print type(a)
    
    
In [32]:
    
class classA(object):
    pass
a = classA()
print type(a)
    
    
In [33]:
    
class evenInt(int):
    def __init__(self, value):
        if value % 2 != 0:
            raise ValueError(str(value)+
                             ' is not even')
        super(evenInt, self).__init__(value)
a = evenInt(24)
b = 9
a+b
    
    Out[33]:
In [30]:
    
class defaultdict(dict):
    def __init__(self, default=None):
        dict.__init__(self)
        self.default = default
    def __getitem__(self, key):
        try:
            return dict.__getitem__(self, key)
        except KeyError:
            return self.default
a = defaultdict(default=0.0)
print a
a['x1'] = 1
print a['x1']
print a
print a['x2']
a.y = '7'
print a.y
print a.__dict__
    
    
In [3]:
    
class defaultdict(dict):
    __slots__ = ['default']
    def __init__(self, default=None):
        dict.__init__(self)
        self.default = default
    def __getitem__(self, key):
        try:
            return dict.__getitem__(self, key)
        except KeyError:
            return self.default
a = defaultdict(default=0.0)
print a
a['x1'] = 1
print a['x1']
print a
print a['x2']
#a.y = '7'
#print a.y
#print a.__dict__
print a.__slots__
    
    
In [2]:
    
class defaultdict(dict):
    __slots__ = ['default']
    def __init__(self, default=None):
        dict.__init__(self)
        self.default = default
    def __getitem__(self, key):
        try:
            return dict.__getitem__(self, key)
        except KeyError:
            return self.default
a = defaultdict(default=0.0)
print a
a['x1'] = 1
print a['x1']
print a
print a['x2']
#a.y = '7'
#print a.y
#print a.__dict__
print a.__slots__
a.__slots__.append('y')
print a.__slots__
a.y = '7'
print a.y
    
    
    
Some notes on slots:
__slot__ subclasses
In [ ]: