object values in a list

This is the place for queries that don't fit in any of the other categories.

object values in a list

Postby emmauk » Sat Oct 26, 2013 6:34 pm

Hello,

I am new to Python and OOP in general, although I do programme in other languages. I am hoping you will be able to help me understand a script I have inherited or at least give me the correct terminology to help my searches. I did try searching for the answer but object, value and list are so common I didn't have much luck narrowing my search.

The script (shown at the bottom) creates a Dataset using the netCDF library, it then loops through each record assigning the Dataset variable values to an instance of class. The class instance is then added to a list.

The difficulty I am having is with seeing the values held in the list. If I do a simple print as I would for seeing a normal list I get this result:
Code: Select all
print output_data
[<__main__.OutputData instance at 0x92dc20c>, <__main__.OutputData instance at 0x940b16c>, <__main__.OutputData instance at 0x940b18c>]
So I tried a other ways:
Code: Select all
print dir(output_data)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

print dir(output_data.__getitem__)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

print output_data.__getitem__
<built-in method __getitem__ of list object at 0x94ba04c>
I've also tried loops and [:] all manor of things but I just can't quite get there, any help you can give me would be much appreciated.

If it helps, this is the full code:
Code: Select all
def read_netcdf(dir_name):

    """work out which netcdf files to read in"""

    import sys
    import time
    from datetime import date
    from datetime import timedelta
    from datetime import datetime
    import os

    # get a list of files in the directory
    files = os.listdir(dir_name)
   
    # create empty lists to store the files that we're interested in
    posmv_pos = list()
    met = list()

    for i in files:

        if "position-Applanix" in i:

            posmv_pos.append(i)

        elif "-MET-" in i:

            met.append(i)

    # sort the files so that they're in file name order, which will also
    #  be date and time order
    posmv_pos.sort()
    met.sort()


    today_str = "20131018"
    tomorrow_str = "20131019"


    posmv_to_open = list()

    for i in posmv_pos:

        if (today_str in i) or (tomorrow_str in i):

            posmv_to_open.append(dir_name + "/" + i)

    print posmv_to_open

    met_to_open = list()

    for i in met:

        if (today_str in i) or (tomorrow_str in i):

            met_to_open.append(dir_name + "/" + i)      

    #print met_to_open


    from numpy import float64
    from netCDF4 import num2date
    from netCDF4 import date2num
    from netCDF4 import Dataset

    f = Dataset(posmv_to_open[0], 'r', 'NETCDF3_CLASSIC')

    # print f
    # <type 'netCDF4.Dataset'>
    # root group (NETCDF3_CLASSIC file format):
    # history: TECHSAS v.2.35 - 2006-09-23T02:56:27 UTC 2013-10-18T09:27:15Z
    # source: Acquisition of Applanix_GPS_DY1
    # conventions: CF-1.0.
    # creationtime: 2013-10-18T09:27:15Z
    # device_firstusedate: 2000-01-01T00:00:00Z
    # device_deviceid: Applanix_GPS_DY1
    # device_devicename: Applanix_GPS_DY1
    # device_position: UpTop
    # device_installdate: 2000-01-01T00:00:00Z
    # device_latestcalibrationdate: 2000-01-01T00:00:00Z
    # device_sourcetype: gps
    # firstframetime: 2013-10-18T09:27:16Z
    # lastframetime: 2013-10-19T08:59:59Z
    # device_X: 0.0
    # device_Y: 0.0
    # device_Z: 0.0
    # frame_name: position
    # frame_major: 1
    # frame_minor: 0
    # frame_sourcetype: gps
    # frame_period: 1.0
    # title: Techsas 2.35
    # institution: Ifremer
    # reference: http://www.ifremer.fr
    # dimensions: time
    # variables: measureTS, lat, long, alt, prec, mode, gndcourse, gndspeed, time
    # groups:


    # vars for loops below
    current_time = datetime(2050,12,31,23,59,59)
    cmg_total = 0
    cmg_values = 0
    smg_total = 0
    smg_values = 0

    class OutputData:
        time_val = datetime(2050,12,31,23,59,59)
   lat = float64(0.0)
   lon = float64(0.0)
   smg = float64(0.0)
   cmg = float64(0.0)
   heading = float64(0.0)
   speed = float64(0.0)
   direct = float64(0.0)
   airtemp = float64(0.0)
   humid = float64(0.0)
   
    output_data = list()

    # while conditions
    l = 0
    num_records = len(f.variables['measureTS'])
    test_nums = num_records / 1000 # fewer records while testing
    while l < test_nums:
          
   output_val = OutputData()
   output_val.time_val = current_time
   output_val.lat = f.variables['lat'][l]
   output_val.lon = f.variables['long'][l]

   if cmg_values > 0:
       output_val.cmg = cmg_total/cmg_values
   else:
       output_val.cmg = 0

   if smg_values > 0:
       output_val.smg = smg_total/smg_values
   else:
       output_val.smg = 0
   
   output_data.append(output_val)
   #print output_data.__getitem__

   cmg_total = 0
   cmg_values = 0
   smg_total = 0
   smg_values = 0

   l = l + 1
    f.close()
emmauk
 
Posts: 7
Joined: Sat Oct 26, 2013 5:23 pm

Re: object values in a list

Postby hrs » Sat Oct 26, 2013 8:10 pm

The code indentation doesn't make much sense. Please check and make sure that the posted code has the same indentation as your program file.
hrs
 
Posts: 86
Joined: Thu Feb 07, 2013 9:26 pm

Re: object values in a list

Postby emmauk » Sat Oct 26, 2013 8:49 pm

Sorry about that it was showing as properly indented in the reply window, but when it went to preview half the code had shifted. It should be correct now.
Code: Select all
import xml.dom.minidom

def read_netcdf(dir_name):

    """work out which netcdf files to read in"""

    import sys
    import time
    from datetime import date
    from datetime import timedelta
    from datetime import datetime
    import os

    # get a list of files in the directory
    files = os.listdir(dir_name)
   
    # create empty lists to store the files that we're interested in
    posmv_pos = list()
    met = list()

    for i in files:

        if "position-Applanix" in i:

            posmv_pos.append(i)

        elif "-MET-" in i:

            met.append(i)

    # sort the files so that they're in file name order, which will also
    #  be date and time order
    posmv_pos.sort()
    met.sort()


    today_str = "20131018"
    tomorrow_str = "20131019"


    posmv_to_open = list()

    for i in posmv_pos:

        if (today_str in i) or (tomorrow_str in i):

            posmv_to_open.append(dir_name + "/" + i)

    print posmv_to_open

    met_to_open = list()

    for i in met:

        if (today_str in i) or (tomorrow_str in i):

            met_to_open.append(dir_name + "/" + i)      

    #print met_to_open


    from numpy import float64
    from netCDF4 import num2date
    from netCDF4 import date2num
    from netCDF4 import Dataset

    f = Dataset(posmv_to_open[0], 'r', 'NETCDF3_CLASSIC')

    # print f
    # <type 'netCDF4.Dataset'>
    # root group (NETCDF3_CLASSIC file format):
    # history: TECHSAS v.2.35 - 2006-09-23T02:56:27 UTC 2013-10-18T09:27:15Z
    # source: Acquisition of Applanix_GPS_DY1
    # conventions: CF-1.0.
    # creationtime: 2013-10-18T09:27:15Z
    # device_firstusedate: 2000-01-01T00:00:00Z
    # device_deviceid: Applanix_GPS_DY1
    # device_devicename: Applanix_GPS_DY1
    # device_position: UpTop
    # device_installdate: 2000-01-01T00:00:00Z
    # device_latestcalibrationdate: 2000-01-01T00:00:00Z
    # device_sourcetype: gps
    # firstframetime: 2013-10-18T09:27:16Z
    # lastframetime: 2013-10-19T08:59:59Z
    # device_X: 0.0
    # device_Y: 0.0
    # device_Z: 0.0
    # frame_name: position
    # frame_major: 1
    # frame_minor: 0
    # frame_sourcetype: gps
    # frame_period: 1.0
    # title: Techsas 2.35
    # institution: Ifremer
    # reference: http://www.ifremer.fr
    # dimensions: time
    # variables: measureTS, lat, long, alt, prec, mode, gndcourse, gndspeed, time
    # groups:


    # vars for loops below
    current_time = datetime(2050,12,31,23,59,59)
    cmg_total = 0
    cmg_values = 0
    smg_total = 0
    smg_values = 0

    class OutputData:
        time_val = datetime(2050,12,31,23,59,59)
        lat = float64(0.0)
        lon = float64(0.0)
        smg = float64(0.0)
        cmg = float64(0.0)
        heading = float64(0.0)
        speed = float64(0.0)
        direct = float64(0.0)
        airtemp = float64(0.0)
        humid = float64(0.0)
   
    output_data = list()

    # while conditions
    l = 0
    num_records = len(f.variables['measureTS'])
    test_nums = num_records / 1000 # fewer records while testing
    while l < test_nums:
          
        output_val = OutputData()
        output_val.time_val = current_time
        output_val.lat = f.variables['lat'][l]
        output_val.lon = f.variables['long'][l]

        if cmg_values > 0:
            output_val.cmg = cmg_total/cmg_values
        else:
            output_val.cmg = 0

        if smg_values > 0:
            output_val.smg = smg_total/smg_values
        else:
            output_val.smg = 0
   
        output_data.append(output_val)
        #print output_data.__getitem__

        cmg_total = 0
        cmg_values = 0
        smg_total = 0
        smg_values = 0

        l = l + 1
    f.close()
emmauk
 
Posts: 7
Joined: Sat Oct 26, 2013 5:23 pm

Re: object values in a list

Postby hrs » Sun Oct 27, 2013 11:48 am

It looks like something half finished.

Imports should be at the top of the file, not within a function definition.
Some imports are not used.
I'm not sure what the point is of defining a class inside a function. I would move it above the function definition, below the imports.
I'm also not sure why you have all those class attributes inside OutputData.
cmg_values and smg_values are always 0. Testing for if cmg_values > 0: will always prove False.
Judging from the print statements in the comments this is for Python 2.x. This means you have floor division. test_nums = num_records / 1000 will be zero if num_records is fewer than 1000 in which case l < test_nums is False. Perhaps this is as intended, I don't know.
As for your question, output_data is just a list. You can loop through its items and look for the values there. But I would fix up the code first.
hrs
 
Posts: 86
Joined: Thu Feb 07, 2013 9:26 pm

Re: object values in a list

Postby emmauk » Sun Oct 27, 2013 12:52 pm

Hello hrs, thank you for your reply.

As mentioned I inherited this script so I'm uncertain as to why things such as the class is inside the function but I can change that. It is a Python 2.6 script but as the file I read in has 83000 enteries the floor division isn't a problem. It just means less screen out put for now, which is easier for me to look at.

Going back to the list, am I doing my for loop wrong? As this is the result:
Code: Select all
    for item in output_data:
        print item
    # <__main__.OutputData instance at 0x8f3da8c>

I was hoping to see the actual values in the list but everything I try ends up with a similar result as above. I am trying to do my own research as well but I am on an extremely limited bandwidth so it's taking a while for me to get to pages. Thanks once again, Emma
emmauk
 
Posts: 7
Joined: Sat Oct 26, 2013 5:23 pm

Re: object values in a list

Postby hrs » Sun Oct 27, 2013 6:48 pm

Code: Select all
for item in output_data:
    print item.time_val, item.lat, item.lon
hrs
 
Posts: 86
Joined: Thu Feb 07, 2013 9:26 pm

Re: object values in a list

Postby emmauk » Sun Oct 27, 2013 8:07 pm

Well I feel silly now, that works a charm thanks hrs.
Code: Select all
for item in output_data:
    print item.time_val, item.lat, item.lon
# 2050-12-31 23:59:59 50.891737 -1.394816

Out of interest is there a way of seeing the list structure with the values? In my mind a list that holds objects might look something like this:
Code: Select all
[{'time_val' : '2050-12-31 23:59:59', 'lat' : 50.891737, 'lon' : -1.394816},{'time_val' : '2050-12-31 23:59:59', 'lat' : 50.891737, 'lon' : -1.394815}

Or have I got that completely wrong? It would just help me understand how to access the data and how Python works in general.
emmauk
 
Posts: 7
Joined: Sat Oct 26, 2013 5:23 pm

Re: object values in a list

Postby hrs » Sun Oct 27, 2013 8:49 pm

You've got it almost right. The instance attributes are stored in a dictionary. A dictionary is a Python datastructure. They can be accessed via .__dict__.
Code: Select all
>>> class MyClass:
...     class_attribute = 'meh'
...
>>> a = MyClass()
>>> a.instance_attribute1 = 'foo'
>>> a.instance_attribute2 = 'asd'
>>> a.__dict__
{'instance_attribute2': 'asd', 'instance_attribute1': 'foo'}

I don't know how to access class attributes, I've never used them. In your case those class attributes are all numpy.float64(0.0) and are not used in the code you've shown. So you might as well just use a list to store time_val, lat and lon (you can store lists in lists).
hrs
 
Posts: 86
Joined: Thu Feb 07, 2013 9:26 pm

Re: object values in a list

Postby emmauk » Mon Oct 28, 2013 1:30 pm

Thanks for confirming that hrs.

As a side note for anyone who's interested the printr module ( http://www.python-printr.org/) gives me close to what I had imagined - a recursive way of intergating an object, rather than relying on know what attributes to call.
Code: Select all
for item in output_data:
        printr(item)

#<OutputData object>
    {
        lat: 50.89174
        cmg: 0
        time_val: 2050-12-31 23:59:59
        lon: -1.394816
        smg: 0
    }


I would still prefer a way of seeing the objects in a list, like so:
output_data [ { lat: 50.89174, cmg: 0, time_val: 2050-12-31 23:59:59, lon: -1.394816, smg: 0 }, { lat: 50.89174, cmg: 0, time_val: 2050-12-31 23:59:59, lon: -1.394816, smg: 0 }]
Just so it's blantely obvious that the objects are within a list, rather than the programmer having to remember that there's actually a square bracket around the returned values. Anyway ths has given me enough to carry on with so that's great - cheers
emmauk
 
Posts: 7
Joined: Sat Oct 26, 2013 5:23 pm

Re: object values in a list

Postby ochichinyezaboombwa » Mon Oct 28, 2013 9:48 pm

You need to redefine a __repr__(self) in your class.
E.g.
Code: Select all
class Point:
    def __init__(self,x,y):
        self.x, self.y = x,y
    def __repr__(self):
        return "I am a point ad (%s,%s)" % (self.x, self.y)

pp = [Point(33,23), Point(-1, 18)]
for p in pp:
    print p

Output:
Code: Select all
I am a point ad (33,23)
I am a point ad (-1,18)
ochichinyezaboombwa
 
Posts: 200
Joined: Tue Jun 04, 2013 7:53 pm


Return to General Coding Help

Who is online

Users browsing this forum: No registered users and 1 guest