Tag Archives: object

Basic OOP Python

I’ve just started with object oriented programming in Python so I thought I’d cover some of the basics here. Please don’t assume this is a thorough tutorial on OOP!

The beauty of OOP is that it allows me to create a template with which I can create objects. The building blocks of the object sit in the class, while the object itself is created from that blueprint with various properties. I can then make as many of these objects as I desire from that single class. I can see this being very beneficial for certain types of programming (games especially)

Basics

I’ll start with something simple. I want to create a class called Ball. This class requires certain properties like radius and colour. I’ll create a class like so:

class Ball:
    def __init__(self, radius, colour):
        self.radius = radius
        self.colour = colour

I’ve created a class called ‘Ball’ – This requires two variables, radius and colour. Note that ‘self’ refers to the object that is being created. Once this is done, I can then call this class to create objects. I need to ensure I pass both variables otherwise:

>>>blueball = Ball("Blue")

Traceback (most recent call last):
  File "", line 1, in 
    blueball = Ball("Blue")
TypeError: __init__() takes exactly 3 arguments (2 given)

Let’s do it properly:

>>>blueball = Ball(10, "Blue")

blueball is now an object created from the class:

>>> blueball
<__main__.Ball instance at 0x10f11bdd0>
>>> print type(blueball)
type 'instance'

Each self.x in the class is a method which I can set and interrogate. If I wanted to see the current radius of blueball, I simply call the method I defined:

>>> blueball.radius
10

I can also change the variable later if I so choose:

>>> blueball.radius = 20
>>> blueball.radius
20

If I simply print blueball, I won’t get much:

>>> print blueball
<__main__.Ball instance at 0x10f11bdd0>

In order to be able to get string output from an object, I need to ensure the class has a string method. I’ll add the following to my original class:

class Ball:
	def __init__(self, radius, colour):
		self.radius = radius
		self.colour = colour
    def __str__(self):
		return "I am a " + self.colour + " ball, with a radius of " + str(self.radius)

Note that my old blueball variable has still been created from the old class so I’ll simply create a new one:

>>> blueball = Ball(10, "Blue")
>>> print str(blueball)
I am a Blue ball, with a radius of 10

I can now happily create as many objects as I want, with different properties. Each object is a separate instance:

>>> redball = Ball(20, "Red")
>>> print str(redball)
I am a Red ball, with a radius of 20


Let’s take this a step further. For this I’m going to use Scott Rixner’s CodeSkulptor as it has some nice draw capabilties built-in. It also runs in your browser directly.

I’d like to create an empty space with nothing. I then want to click a button to create a new ball with random properties. That ball should then be displayed inside the space. Each click should be a new object created from my original class. I’m going to add a few more properties to my class which will come clear later.

I’ll first get my global variables set:

list_of_balls = []
width = 1000
height = 600
colours = ["Aqua","Blue","Green","Lime","Maroon","Navy","Orange","Red","White","Yellow"]

Now comes the Ball class:

class Ball:
    def __init__(self, radius, mass, colour, x_location):
        self.radius = radius
        self.mass = mass
        self.colour = colour
        self.location = [x_location, height/2]

When I click the mouse button, I want certain random properties set for the object:

def click():
    radius = random.randint(1,40)
    mass = radius
    colour = random.choice(colours)
    x_location = random.randint(20, width-20)
    new_ball = Ball(radius, mass, colour, x_location)
    list_of_balls.append(new_ball)

The mouse click handler creates a new ball with random properties, then appends that ball to a list of balls. Each time I click a new ball is added to the list.

I now need to draw the balls. I need to iterate through my list of objects and draw each one:

def draw(canvas):
    for ball in list_of_balls:
        canvas.draw_circle((ball.location[0],ball.location[1]), ball.radius, 1, ball.colour, ball.colour)

Click here to view and run the code in CodeSkulptor. Press play in the top left corner to run the code.

Dynamic

So the above code simply creates a bunch of balls on random places on the x axis while being in the middle of the y axis. Let’s start moving these balls around based on their initial mass. Currently the bigger the ball, the bigger the mass. Let’s keep it that way for now. All balls will simply fall towards the ground. I’d like to make sure that when the ball hits the bottom of the screem it’s reflected back up. Same goes for the top of the screen.

First I need to add velocity to the object. Note that properties of an object don’t all have to be variables. I could set the velocity of all the balls exactly the same. For now I’ll use the mass of the ball:

class Ball:
    def __init__(self, radius, mass, colour, x_location):
        self.radius = radius
        self.mass = mass
        self.velocity = self.mass
        self.colour = colour
        self.location = [x_location, height/2]

I then need to update my draw handler so it updates the position of each ball. If the y location of the ball hits the top or bottom of the screen, reverse the direction:

def draw(canvas):
    for ball in list_of_balls:
        ball.location[1] += ball.velocity
        if ball.location[1] >= (height - ball.radius) or ball.location[1] <= ball.radius:
            ball.velocity = -ball.velocity
        canvas.draw_circle((ball.location[0],ball.location[1]), ball.radius, 1, ball.colour, ball.colour)

Click here to open my code in CodeSkulptor. Now every time you add a new ball, it’ll start bouncing against the top and bottom wall. Create as many balls as you like!

Conclusions

It’s still early days in my OOP work. I can see this method is perfect for applications like gaming. I’m not 100% sure if I’ll have an application for it in my type of coding, I’ll have to see.

In the interim, the basics of OOP isn’t that difficult. I’ve still got a long way to go but happy so far!

For future work on my code above, it would be trivial to set a random mass. It would also be nice to extend the balls to simply bounce like in real life, or gets the balls to bounce off each other. Either way, the properties of each ball itself is independent of the environment in which it sits.

Reliable static routing without the need for the data license

Sometimes it’s required that you have a number of static routes on a router, maybe for management or some other reason. If the static route point to a next-hop, but the exit interface stays up, there is no way for the router to know that it’s sending traffic down a black hole. Let’s show the following diagram as an example:
reliable static Reliable static routing without the need for the data license

R2 is a CPE on site. It has a primary link on fa0/0 connected to both R3 and R4 through a switch/VPLS. R2 is running OSPF with R3 and R4 and also has a floating static default route to R4′s fa0/0 interface. If this link goes down, the floating static route should come into play and take over. While the link is up we have a static route on R2 that sends our management traffic (10.0.0.0/24) to R4′s fa0/0 interface.

R3 is originating a default route via OSPF.

But does this actually work? Let’s configure it up quickly first and then break R2′s primary link.

R3:

interface FastEthernet0/0
 ip address 192.168.234.3 255.255.255.0
 ip ospf 1 area 0
!
router ospf 1
 default-information originate always

R4:

interface FastEthernet0/0
 ip address 192.168.234.4 255.255.255.0
 ip ospf 1 area 0
!
interface Serial0/0
 ip address 24.24.24.4 255.255.255.0

R2

interface FastEthernet0/0
 ip address 192.168.234.2 255.255.255.0
 ip ospf 1 area 0
!
interface Serial0/0
 ip address 24.24.24.2 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 24.24.24.4 200
ip route 10.0.0.0 255.255.255.0 192.168.234.4

Let’s have a look at R2′s routing table:

R2#   sh ip route | begin Gate
Gateway of last resort is 192.168.234.3 to network 0.0.0.0

C    192.168.234.0/24 is directly connected, FastEthernet0/0
     24.0.0.0/24 is subnetted, 1 subnets
C       24.24.24.0 is directly connected, Serial0/0
     10.0.0.0/24 is subnetted, 1 subnets
S       10.0.0.0 [1/0] via 192.168.234.4
O*E2 0.0.0.0/0 [110/1] via 192.168.234.3, 00:01:22, FastEthernet0/0

All looks good. I have my OSPF default route and I also have my management range route to R4.

Now for some reason, R2′s primary link fails. The fa0/0 interface stays up however.The link is dodgy, r there is a mess-up with the VPLS, it doesn’t really matter. What happens then?

R2 loses it’s adjacency with R4, but what about our management traffic?

R2#   sh ip route | begin Gate
Gateway of last resort is 24.24.24.4 to network 0.0.0.0

C    192.168.234.0/24 is directly connected, FastEthernet0/0
     24.0.0.0/24 is subnetted, 1 subnets
C       24.24.24.0 is directly connected, Serial0/0
     10.0.0.0/24 is subnetted, 1 subnets
S       10.0.0.0 [1/0] via 192.168.234.4
S*   0.0.0.0/0 [200/0] via 24.24.24.4

The problem is that we are still sending management traffic off to R4. This is the problem with a static route, it’s static! R2 has a next-hop of 192.168.234.4 – It’s interface in this subnet is still up, and so the router is trying to ARP for 192.168.234.4. Of course R4 never responds but the router will continue to try. It’ll never fail over to the backup.

Now with reliable static routing you are able to generate an IP Sla object which consistently pings another interface. If you get no response you cause the track object to go down and hence the static route goes down. The problem with this is that you need an expensive data license for the privilege of doing this.

But track objects can track a lot more than just IP Sla objects. You can also track routes. So why not track the default route considering we are learning that through the primary link? If the primary fails and OSPF times out, we will remove the OSPF default. Let’s try and see what happens:

R2:

track 1 ip route 0.0.0.0 0.0.0.0 reachability
!
ip route 10.0.0.0 255.255.255.0 192.168.234.4 track 1

Some of you may see a problem here, but bear with me.

Let’s see if this has fixed the problem:

R2#   sh ip route | begin Gate
Gateway of last resort is 24.24.24.4 to network 0.0.0.0

C    192.168.234.0/24 is directly connected, FastEthernet0/0
     24.0.0.0/24 is subnetted, 1 subnets
C       24.24.24.0 is directly connected, Serial0/0
     10.0.0.0/24 is subnetted, 1 subnets
S       10.0.0.0 [1/0] via 192.168.234.4
S*   0.0.0.0/0 [200/0] via 24.24.24.4

Hmm, we are still sending traffic to R4′s fa0/0 interface. Why is this?

R2#sh track 1
Track 1
  IP route 0.0.0.0 0.0.0.0 reachability
  Reachability is Up (static)
    1 change, last change 00:04:22
  First-hop interface is Serial0/0
  Tracked by:
    STATIC-IP-ROUTING 0

The problem is that our floating static route went live. As soon as it did we had a default route again and hence the track object is now UP.

But you don’t HAVE to track a default route. Why don’t we simply inject a phantom prefix on R3? One that will simply be used for tracking?

R3:

interface Loopback1
 ip address 3.3.3.3 255.255.255.255
 ip ospf 1 area 0

R2:

R2#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
R2(config)#no track 1
R2(config)#track 1 ip route 3.3.3.3/32 reachability

R2 is now tracking the loopback route from R3:

R2#sh track 1
Track 1
  IP route 3.3.3.3 255.255.255.255 reachability
  Reachability is Up (OSPF)
    2 changes, last change 00:00:03
  First-hop interface is FastEthernet0/0
  Tracked by:
    STATIC-IP-ROUTING 0
R2#   sh ip route | begin Gate
Gateway of last resort is 192.168.234.3 to network 0.0.0.0

     3.0.0.0/32 is subnetted, 1 subnets
O       3.3.3.3 [110/11] via 192.168.234.3, 00:00:24, FastEthernet0/0
C    192.168.234.0/24 is directly connected, FastEthernet0/0
     24.0.0.0/24 is subnetted, 1 subnets
C       24.24.24.0 is directly connected, Serial0/0
     10.0.0.0/24 is subnetted, 1 subnets
S       10.0.0.0 [1/0] via 192.168.234.4
O*E2 0.0.0.0/0 [110/1] via 192.168.234.3, 00:00:24, FastEthernet0/0

R2 now loses OSPF adjacency:

R2#
*Mar  1 00:38:51.919: %OSPF-5-ADJCHG: Process 1, Nbr 192.168.234.3 on FastEthernet0/0 from FULL to DOWN, Neighbor Down: Dead timer expired
R2#
*Mar  1 00:38:55.239: %OSPF-5-ADJCHG: Process 1, Nbr 192.168.234.4 on FastEthernet0/0 from FULL to DOWN, Neighbor Down: Dead timer expired
R2#
*Mar  1 00:39:05.307: %TRACKING-5-STATE: 1 ip route 3.3.3.3/32 reachability Up->Down
R2#
R2#sh track 1
Track 1
  IP route 3.3.3.3 255.255.255.255 reachability
  Reachability is Down (no route)
    3 changes, last change 00:00:11
  First-hop interface is unknown
  Tracked by:
    STATIC-IP-ROUTING 0
R2#   sh ip route | begin Gate
Gateway of last resort is 24.24.24.4 to network 0.0.0.0

C    192.168.234.0/24 is directly connected, FastEthernet0/0
     24.0.0.0/24 is subnetted, 1 subnets
C       24.24.24.0 is directly connected, Serial0/0
S*   0.0.0.0/0 [200/0] via 24.24.24.4

R2 loses the track route, removes the static and install the floating static route. All is good :)

I know there are better ways of doing the above. As in advertise management ranges via OSPF or running BFD, but not all of these are always available, especially over back up links.