Python Records

  • Richard Scott
    Participant

    Hello,

    I am new to Python and wonder how everyone is delivering the following content in Software Design and Development:

    • Records
    • Arrays of records

    Firstly I am assuming that everyone is using Python Lists to implement Arrays (rather than the array module through import array) – please let me know if you are using proper arrays in Python rather than lists.

    The two methods I have come across:

    1. Libraries
      Here is an excerpt from a short game I wrote:

      rooms={
              1:{'name':'Hall',
                 'desc':'The hallway has doors to the east and south',
                 's':{'dest':3,'lock':''},
                 'e':{'dest':2,'lock':''},
                 'item':''},
              2:{'name':'Bedroom',
                 'desc':'The bedroom has doors to the west and south',
                 's':{'dest':4,'lock':'key'},
                 'w':{'dest':1,'lock':''},
                 'item':''}
      }
    2. Objects
      Here is the same data as OOP objects:

      class direction():
          def __init__(self):
              self.dest = -1
              self.lock = ''
      
      class room():
          def __init__(self):
              self.roomname = ''
              self.desc = ''
              self.n = direction()
              self.s = direction()
              self.w = direction()
              self.e = direction()
              self.item = ''
      
      rooms = []
      rooms.append( room() )
      rooms.append( room() )
      rooms.append( room() )
      rooms.append( room() )
      rooms.append( room() )
      
      rooms[0].roomname = 'outside'
      rooms[0].desc = 'You have escaped and are outside the house.'
      rooms[0].n.dest = 4
      
      rooms[1].roomname = 'hall'
      rooms[1].desc = 'The hallway has doors to the east and south'
      rooms[1].s.dest = 2
      rooms[1].e.dest = 3
      

    Are there similar to the methods you use? Perhaps I am missing a simpler way to implement records and arrays of records?

    The first method could be adapted by creating an array of library objects as follows:

    rooms = [
                {'roomname':'hall','area':200},
                {'roomname':'kitchen','area':220},
                {'roomname':'bedroom','area':300},
                {'roomname':'bathroom','area':210}
            ]

    Are any of these along the same lines as anyone else?

    Thanks,

    Richard

    Lee Murray
    Participant

    Hi Richard,

    I used the Class method like you described in your second example. My reasons for choosing that method is that it segues nicely to Classes in Advanced Higher and it feels like the easiest way to group mixed and related variables under a single identifier.

    I’m not a fan of dictionaries (your first example) for a few reasons, but mostly because I find them difficult to work with.

    Regarding arrays, I use Lists. The only negative I can see from using lists is that you don’t need to declare a data type or a size, but when it comes to ‘arrays of records’, there’s a nice way to show both.

    Class Person:
        def __init__(self):
            self.name = ""
            self.age = 0
    
    # declare array of 10 Person objects
    people = [Person() for i in range(10)]
    
    people[0].name = "Lee"
    people[0].age = 21

    Hope this is helpful.

    Richard Scott
    Participant

    Thank you everyone for your advice and help here.

    I really like the dictionary objects in Python (a natural container for JSON data) but their lack of ordering limits their flexibility for this course.

    I will move forward to deliver records using lists of class instances while providing a gentle introduction to OOP.

    A few people have advised using…

    Class Person:
        name = 
        year = 0
    Richard Scott
    Participant

    Thank you everyone for your advice and help here.

    I really like the dictionary objects in Python (a natural container for JSON data) but their lack of ordering limits their flexibility for this course.

    I will move forward to deliver records using lists of class instances while providing a gentle introduction to OOP.

    A few people have advised using…

    Class Person:
        name = ''
        year = 0
    

    as opposed to:

    Class Person:
        def __init__(self):
            self.name = ''
            self.age = 0

    and I am still debating with myself whether to simplify it in this way. Python 3.7 can cope with attributes in this way, even although technically they should be regarded as class level attributes rather than instance level attributes (which we usually want, especially for use as ‘records’) BUT it falls down when nesting class objects as I found out when implementing the simple game touched on in my original post.

    Also I like the workaround of using ‘str’, ‘float’, ‘bool’ and ‘int’ to define datatypes in a class but would adapt this to empty functions to provide workable default data for any instances. So my (probably) preferred technique is…

    Class Person:
        def __init__ (self):
            self.name = str()
            self.year = int()
            self.avegrade = float()
            self.paid = bool()

    These default to:

    ''
    0
    0.0
    False

    but the default values can easily be changed by placing the desired value in the brackets.

    As I say, I am still debating the merits of simplifying the class structure by removing the constructor for Higher level…

    Alasdair Sharp
    Participant

    You can avoid having to define the __init__ constructor and set the attribute types by using a dataclass decorator.
    I’ve found this is quite a nice middle ground.
    Basically the code would go from this:

    Class Person:
        def __init__ (self):
            self.name = str()
            self.year = int()
            self.avegrade = float()
            self.paid = bool()

    to this:

    @dataclass
    Class Person:
        name:str
        year:int
        avegrade:float
        paid:bool
    Mark Hay
    Participant

    Cheers for reminding Alasdair. Might convert my Higher material to that and leave the classes in for AH.

    Denis Soames
    Participant

    I find 2D arrays useful teaching too, there is lots of comparison and reference in tasks and exam questions, plus it provides context to AH students of the ‘old way’ and the new way.

    myArray = [[‘Bob’,15],[‘Fred’,45]]

    OR

    myArray.append([‘Bob’,15])

    and I also do a lot of work with reading 2D files, Excel CSV files which helps with the file reading and writing elements.

    My fav challenge: I give them 140,000 number plates to sort through and pick out those that are speeding and those with fake plates, about 20,000 or so and they make a new file.

    Liz Moran
    Participant

    I want to initialise an integer array/list in a dataclass. How do I do this?

    kerry mcmahon
    Participant

    Hi liz, not totally sure of what you’re asking as You’d create an array of classes (records) for higher, not a class with arrays. So within your class, you are essentially creating a set of fields for the record which you store in the array. Do you mean how do you initialise an integer in the class? If so, you’d do something like the following :
    Class pupil:
    Age:int =0

    Is this what you meant? Apologies if I’ve picked this up the wrong way

    Kerry

    Peter Thoresen
    Participant

    Hi Liz

    If you want to initialise an array of integers, then use something like:
    intarray = [0] * 20

    DataClasses are used to define ‘records’, with optional default values:
    from dataclasses import dataclass
    @dataclass
    class Position:
    name: str
    lon: float = 0.0
    lat: float = 0.0

    To create the array or records:
    classArray = [Position() for x in range(20)]

    Lee Murray
    Participant

    You can include a list in a dataclass, but it’s not exactly straight forward. Here’s an example:

    
    from dataclasses import dataclass, field
    
    @dataclass
    class Pupil:
      pupil_name: str = ""
      subjects: list = field(default_factory=list)
    
    p1 = Pupil()
    p1.name = "Jeff"
    p1.subjects.append("Maths")
    p1.subjects.append("English")
    p1.subjects.append("Computing")
    
    print(p1.subjects)
    

    https://repl.it/@LeeMurray/Python-3-10

    If you want a list of integers, you append integers instead of strings.

    Sean Stratton
    Participant

    Yeah I would use list comprehension with dataclasses.

    Here is my example code

    from dataclasses import dataclass

    @dataclass
    class pupil():
    number:int
    name:str
    age:int

    regClass=[pupil(0,””,0)]*2 # wrong way

    regClass2=[pupil(x+1,””,0) for x in range(2)]

    array=[0 for x in range(10)] # Array(10) of integer

    print(“——————-WRONG——————-“)
    print(regClass)
    regClass[0].name=”Bob”
    print(regClass)
    print(“——————-RIGHT——————-“)
    print(regClass2)
    regClass2[0].name=”Bob”
    print(regClass2)

    You can see from the output that “the wrong way” of setting up an array, results in an array of the same record. While the right way gives an array of different records.

    List Comprehensions in Python

    Liz Moran
    Participant

    Thanks everyone, with your help my array problem is sorted and the program is now working. Liz

Viewing 13 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic.