3

As a simple example, let's assume that we want to create a lot of Earthquake instances, having name, origin time, and hypocenter coordinate attributes coming from other sources encoded as strings ("Nepal 25-4-2015T11:56:26 28.14 84.71 15.0").

class Earthquake(object):
    def __init__(self, strline):
        ....

So, what we must do is:

  1. parse the string to receive name, date, time, latitude, longitude and depth.

  2. instantiate Earthquake by passing those values to initialization call __init__.

Imagine the first part is done by a simple function:

import datetime as dt

def myfunc(strline):
    items = line.split()
    name = items[0]
    otime = dt.datetime.strptime(items[1], "%d-%m-%YT%H:%M:%S")
    lat, lon, depth = map(float, items[2:])

Now I want to use the class class Earthquake to create Earthquake objects in a way that each object has attributes Earthquake.name, Earthquake.otime, Earthquake.lat, Earthquake.lon and Earthquake.depth.

How can I call myfunc method in __init__ method in a class to initialize an object with above attributes?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437

2 Answers2

6

I would do that completely the other way around. Parsing that string is clearly part of what an Earthquake object should do, so provide it as an alternate constructor using a class method:

class Earthquake(object):

    def __init__(self, name, otime, lat, lon, depth):
        self.name = name
        self.otime = otime
        self.lat = lat
        self.lon = lon
        self.depth = depth

    @classmethod
    def from_string(cls, strline):
        items = line.split()
        name = items[0]
        otime = dt.datetime.strptime(items[1], "%d-%m-%YT%H:%M:%S")
        lat, lon, depth = map(float, items[2:])
        return cls(name, otime, lat, lon, depth)

Now you call e.g.:

quake = Earthquake.from_string("Nepal 25-4-2015T11:56:26 28.14 84.71 15.0")

Or, if you want the function to remain standalone, add a return to it:

def myfunc(strline):
    ...
    return name, otime, lat, lon, depth

and make the class method call it:

class Earthquake(object):

    ...

    @classmethod
    def from_string(cls, strline):
        return cls(*myfunc(strline))

(if this syntax is unfamiliar, see What does ** (double star) and * (star) do for parameters?)

Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
3

One of the things you could do is call Earthquake with the string as a parameter and on __init__ you call the parsing function.

import datetime as dt

class Earthquake(object):
    def __init__(self, strline):
        self.parse_data(strline)

    def parse_data(self, strline):
        items = line.split()
        self.name = items[0]
        self.otime = dt.datetime.strptime(items[1], "%d-%m-%YT%H:%M:%S")
        self.lat, self.lon, self.depth = map(float, items[2:])
Vicyorus
  • 260
  • 1
  • 14
  • Some linters will complain that you're setting instance attributes outside of `__init__`. This also makes it slightly more difficult to test the class, as there's no way to initialise it without formatting the input data into the string required. – jonrsharpe Jun 24 '15 at 15:12