Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Object Oriented Programming
#1
Hi there,

I am learning Object Oriented Programming. I do not understand some points in following code. Could you answer me some questions?

# States of a computer

class ComputerState(object):
    """ Abstract base class of state of a computer """
    
    name = "state"
    allowed = []
    
    def switch(self, state):
        """ Switch to new state """
        if state.name in self.allowed:
            print 'Current:',self,' => switched to new state',state.name         
            self.__class__ = state
        else:
            print 'Current:',self,' => switching to',state.name,'not possible.'

    def __str__(self):
        return self.name
    
class Off(ComputerState):
    """ State being switched off """

    name = "off"
    allowed = ['on']

class On(ComputerState):
    """ State of being powered on and working """

    name = "on"
    allowed = ['off','suspend','hibernate']

class Computer(object):
    """ A class representing a computer """

    def __init__(self, model='HP'):
        self.model = model
        # State of the computer - default is off.
        self.state = Off()

    def change(self, state):
        """ Change state """

        self.state = self.state.switch(state)

if __name__ == "__main__":
    comp = Computer()
    # Switch on
    comp.change(On)
The questions are following.
1. Why can we use syntax "self.state.switch(state)" at line 43?
I really do not understand this point, but I think this point has relation with line 38. At line 38, the __init__ constructor initializes the "self.state" variable by invoking "Off" class. After invoking "self.state", "self.state" becomes an object (I call A object), and A object can invoke the method "switch" of "ComputerState" class. Is my understanding correct?

2. What is "state.name" at line 11?
As far as I know, if we use the dot operator, it is a kind of object's attribute accessing.
But I do not understand why "state" is an object? Which line in the code that we create object "state"?

I appreciate for any help.
Reply
#2
In fact this code breaks an important rule in OOP (yes everything is possible in python). The line
self.__class__ = state
changes the type of the instance self. In normal OOP, an instance's class cannot be changed during its lifetime. In this code, the switch() method expects the 'state' argument to be a subclass of ComputerState, namely On or Off, and this is going to be the new type of the self object.

This is not the standard way to code such a feature.

Here is perhaps a more traditional way to code this, still with reified computer states
# States of a computer
 
class ComputerState(object):
    """Class of state of a computer """
    def __init__(self, name):
        self.name = name
        self.successors = []

    def __str__(self):
        return self.name
    
state_graph = {
    'off': ['on'],
    'on': ['off', 'suspend', 'hibernate'],
    'suspend': ['on', 'hibernate'],
    'hibernate': ['on', 'off']
}

# create the ComputerState instances and store them in a dict
states = {}
for w in state_graph:
    states[w] = ComputerState(w)
for w, s in state_graph.items():
    states[w].successors[:] = [states[x] for x in s]

class Computer(object):
    """ A class representing a computer """
 
    def __init__(self, model='HP'):
        self.model = model
        # State of the computer - default is off.
        self.state = states['off']
 
    def change(self, state):
        """ Change state """
 
        if state not in self.state.successors:
            raise ValueError(
                ('Current:', self.state.name, ' => switching to', state.name, 'is not possible'))
        print 'Current:', self.state.name, ' => switched to', state.name
        self.state = state
 
if __name__ == "__main__":
    comp = Computer()
    # Switch on
    comp.change(states['on'])
Reply
#3
First where did you get this code ?
You might consider changing to python 3.

1. Yes. self.state = Off object and Off inherit from ComputerState.

2. State is an object that looking for variable name. Since name isn't in the object. It looks for it in the class. Just basic scoping rules.
99 percent of computer problems exists between chair and keyboard.
Reply
#4
(Aug-21-2018, 12:42 PM)Windspar Wrote: First where did you get this code ?
You might consider changing to python 3.

1. Yes. self.state = Off object and Off inherit from ComputerState.

2. State is an object that looking for variable name. Since name isn't in the object. It looks for it in the class. Just basic scoping rules.

Thank you for your reply.

Quote:First where did you get this code ?
You might consider changing to python 3.

I come across to see this code in github when I search the materials for learning Object Oriented Programming and State Machine design by Python. It is in below link.
https://gist.github.com/pythonhacker/0cd...d18c8667eb

Compare to original code of above link, I have reduced some code lines in my post thread.

The code is originally written by Python 2.x. I will consider changing it to Python 3.

Quote:1. Yes. self.state = Off object and Off inherit from ComputerState.

I got it. Thanks.

Quote:2. State is an object that looking for variable name. Since name isn't in the object. It looks for it in the class. Just basic scoping rules.

As your explanation, I can understand that "state" is an object. That object can look for "name" variable in the class.
But if possible, could you tell me how is the "state" object created? Or is it a special object of python?
Basically, as I know, an object is created from a class as following.

class A():
...

object_A = A()

-> object_A is created from class A.

But in my posted code, I can not see where "state" object is created.

Thanks.
Reply
#5
(Aug-22-2018, 02:51 AM)jackbk Wrote: But in my posted code, I can not see where "state" object is created.
In your code, a state object is created by the line
self.state = Off()
but as I said above, this code is a bad example of Object Oriented Programming because of the line
self.__class__ = state
Reply
#6
Let correct myself.
2. Line 48 is pass the class.
comp.change(On)
line 13 is changes where class belong to.
self.__class__ = state
Classes can be use like a static type. Which is known in python as class variables.
print(On.name)
99 percent of computer problems exists between chair and keyboard.
Reply
#7
Example
class State:
    def __init__(self, name, allow):
        self.name = name
        self.allow = allow

    def switch(self, state):
        if state.__name__.lower() in self.allow:
            return state()
        return self


    def __str__(self):
        return self.name

class On(State):
    def __init__(self):
        State.__init__(self, 'on', ['off', 'suspend'])

class Off(State):
    def __init__(self):
        State.__init__(self, 'off', ['on'])

class Computer:
    def __init__(self):
        self.state = Off()

    def change(self, state):
        self.state = self.state.switch(state)
        print(self.state)

def main():
    c = Computer()
    c.change(On)
    c.change(Off)
    c.change(Off)
    c.change(On)

main()
Example
class State:
    def __init__(self, name, allow):
        self.name = name
        self.allow = allow

    def switch(self, state):
        if state.name in self.allow:
            return state
        return self

    def __str__(self):
        return self.name

class Computer:
    state_on = State('on', ['off', 'suspend'])
    state_off = State('off', ['on'])
    state_suspend = State('suspend', ['on', 'off'])

    def __init__(self):
        self.state = Computer.state_off

    def on(self):
        self.state = self.state.switch(Computer.state_on)
        print(self.state)

    def off(self):
        self.state = self.state.switch(Computer.state_off)
        print(self.state)

    def suspend(self):
        self.state = self.state.switch(Computer.state_suspend)
        print(self.state)

def main():
    c = Computer()
    c.on()
    c.off()
    c.suspend()
    c.on()

main()
99 percent of computer problems exists between chair and keyboard.
Reply
#8
(Aug-21-2018, 10:33 AM)Gribouillis Wrote: In fact this code breaks an important rule in OOP (yes everything is possible in python). The line
self.__class__ = state
changes the type of the instance self. In normal OOP, an instance's class cannot be changed during its lifetime. In this code, the switch() method expects the 'state' argument to be a subclass of ComputerState, namely On or Off, and this is going to be the new type of the self object.

This is not the standard way to code such a feature.

Thank you for this notification. I will pay attention for this style of code. It is not the standard.

(Aug-21-2018, 10:33 AM)Gribouillis Wrote: Here is perhaps a more traditional way to code this, still with reified computer states
# States of a computer
 
class ComputerState(object):
    """Class of state of a computer """
    def __init__(self, name):
        self.name = name
        self.successors = []

    def __str__(self):
        return self.name
    

Thanks for the sample code. I will use it as a reference.

(Aug-22-2018, 01:58 PM)Windspar Wrote: Example
class State:
    def __init__(self, name, allow):
        self.name = name
        self.allow = allow
Example
class State:
    def __init__(self, name, allow):
        self.name = name
        self.allow = allow

Thank for your examples. I will refer it for learning OOP and state machine techniques.
Reply
#9
It all depends on your needs.
Example
from enum import Enum

class Computer:
    States = Enum("State", 'on, off, suspend')
    allowed = {States.on: [States.off, States.suspend],
        States.off: [States.on],
        States.suspend: [States.on, States.off]
        }

    def __init__(self):
        self.state = Computer.States.off

    def change(self, state):
        if state in Computer.allowed[self.state]:
            self.state = state
        print(self.state)

if __name__ == '__main__':
    c = Computer()
    c.change(Computer.States.on)
    c.change(Computer.States.off)
    c.change(Computer.States.suspend)
    c.change(Computer.States.on)
    c.change(Computer.States.suspend)
    c.change(Computer.States.off)
99 percent of computer problems exists between chair and keyboard.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Lightbulb Object Oriented programming (OOP) problem OmegaRed94 6 2,860 May-31-2021, 07:19 PM
Last Post: OmegaRed94
  Object Oriented DB Interactions datasundae 2 2,336 May-25-2018, 09:51 PM
Last Post: datasundae
  Oriented Object ldthan 1 2,367 Mar-27-2018, 11:26 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020