5

I have a MyObject which has an x and y coordinate.

as far as I can see, I can store it in three ways:

class MyObject:
    def __init__(self, x, y):
        self.x = x
        self.y = y

class MyObject:
    def __init__(self, x, y):
        self.position = [x, y]

class MyObject:
    def __init__(self, x, y):
        self.position = Coord(x,y) #Coord class created elsewhere

Is there a best practise either way for this ?

Where I'm thinking this is relevant, is when passing these coordinates into other methods:

eg.

myObj = MyObject(0,0)
searchLocation(myObj.x, myObj.y)
searchLocation2(myObj.position)
1
  • 8
    How about a tuple?
    – Doval
    Sep 5, 2014 at 1:51

8 Answers 8

2

If you don't have enough data to decide, chose the most flexible option. The object choice would allow you to have the other two options as properties. (Though I would, as the comment suggests, choose a tuple over a list.)

0

I think that the third implementation of MyObject is the best since it separates the object from the 2D math of the coordinate system. ( you can implement a complete math library for the coordinates and it is completely independent from the objects you create ). Now in order to make the objects more flexible you could create functions that take either two numbers for x and y or a Coord object and be prepared to add more as your system grows.

0

Yeah it depends how much of a "first class citizen" the position is. If lots of other objects consume or produce it and/or there's behaviour to do with positions you want to capture/enforce (as per Gus's answer), then you're probably better off making it its own class.

If you do go for making it its own class, you should definitely move away from taking the x and y elements in the constructor to MyObject and instead make it take a Position object. There's probably no reason why MyObject should be aware of what a Position object needs to be constructed, at least not obviously from the example given (though I accept there may be reasons to not do this in some situations).

0

I think an answer that gets you all the behavior you want with zero code overhead is to use a Pandas Series. It supports accessing by index, accessing by field name (i.e. .x and .y), and it also supports element-wise operations out of the box, so you'll be able to add and subtract your coordinates without having to overload any operators.

0

I would take a look at namedtuple* class from the standard library. It's basically a automated way of subclassing a tuple with named proprties for corresponding to each field.

If you need to do vector and matrix operations you might want to look into NumPy instead, which is made of highly functional numeric datatypes:

0

How often will you use x without y or vice versa? If your answer is rarely or never, then group them together into a tuple or class. Whether to use a tuple or class is another question. One common rule of thumb is to use a class if it will have two or more methods, and otherwise use a tuple. A namedtuple will get you the naming convenience of class members while being as lightweight as normal tuples.

This answer speaks to using namedtuple with points, as in your example.

0

There are several rules I use when doing this. They apply to all kinds of things, not just x and y coordinates, but also to search criteria, sets of flags, sets of numeric parameters, and so on.

That said, not everyone uses these principles, and you can often find high quality code that makes other decisions.

Four or more parameters should usually be refactored into objects

If your function takes four or more parameters, you should try to refactor them into objects that group them together.

The reason is that four parameters for a function is usually just plain too much. In a function call, it gets hard to track which arguments are meant for which parameters, especially if some parameters take a default value or are optional.

Lines of code like these are a quite frustrating to see:

SomeMethod(1, null, null, 1, 0)
SomeMethod(1, 1, 1, null, 5)

In languages that support named formal parameters, this is less of an issue. But usually people don't bother to specify the name of a parameter when they don't have to.

Also, if after refactoring you find yourself still facing a function with four or more parameters, you probably have bigger problems.

Sets of 2+ parameters that appear frequently together should be refactored into objects

This case touches on the coordinates case, since in a project that involves coordinates you will usually have to define many functions that take them as parameters.

If these parameters appear so frequently in method calls, there is probably a strong link between them.

Sets of parameters that control extensible functionality should be put into an object

For example, if you have a method such as:

Search(string name, int age, DateTime date, ...)

Where it makes sense for the list of parameters to be extended with the addition of other criteria, then you should put the set of criteria into an object.

0

If performance is of utmost importance, do store them as two variables. This means less heap objects become allocated, and thus, garbage collection overheads are lower.

Of course, the OP asked about Python so the OP probably doesn't care that much about performance, but somebody may be reading this and using e.g. Java, in which case performance may be important.

Array (or for Python, tuple) could be used if you have a plan for extending the code from 2 dimensions into N dimensions. Otherwise, don't bother.

Not the answer you're looking for? Browse other questions tagged or ask your own question.