John AZ1
John AZ1

Reputation: 187

Make a 2d array list object?

I am trying to make a 2d subclass of the list object called map2d. I want to be able to initialize map2d and get a 2d array of a defined size.

E.g,

class map2d(list):
    def __init__(self,x,y):
        # Magic code that makes this work

 Map = map2d(3,2)
 print(Map)

Output

[[None, None], [None,None], [None,None]]

What I Tried

class map2d(list):
    def __init__(self,x,y):
        self = [[None for _ in range(y)] for _ in range(x)]

I know that this is probably a perversion of everything sacred but it makes sense to me.

Thanks in advance,

John

Upvotes: 0

Views: 66

Answers (2)

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 95948

There is nothing magical about self. When you assign anything to self, e.g. self = whatever that works how assignment always works in Python: now self refers to whatever object whatever referred to. Assignment never mutates. You need to use mutator methods, like .append or .extend or index/slice based assignment. Here's a simple way:

In [1]: class map2d(list):
   ...:     def __init__(self,x,y):
   ...:         for _ in range(x):
   ...:             r = []
   ...:             self.append(r)
   ...:             for _ in range(y):
   ...:                 r.append(None)
   ...:

In [2]: map2d(2,3)
Out[2]: [[None, None, None], [None, None, None]]

However, I see no good reason to use inheritance for this. Just create a helper function:

In [3]: def map2d(x,y):
   ...:     return [[None for _ in range(y)] for _ in range(x)]
   ...:

In [4]: map2d(2,3)
Out[4]: [[None, None, None], [None, None, None]]

Note a list is not an array, and lists don't have "dimensions", they only have a length.

If you really want to prevent negative indexing, you could do:

In [10]: class MyList(list):
    ...:     def __getitem__(self, item):
    ...:         if isinstance(item, int) and item < 0:
    ...:             raise TypeError("MyList indices must be positive")
    ...:         self.__getitem__(item)
    ...:

In [11]: x = MyList()

In [12]: x.append(3)

In [13]: x[-1]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-c30dd0d358dc> in <module>()
----> 1 x[-1]

<ipython-input-10-f2169a236374> in __getitem__(self, item)
      2     def __getitem__(self, item):
      3         if isinstance(item, int) and item < 0:
----> 4             raise TypeError("MyList indices must be positive")
      5         self.__getitem(item)
      6

TypeError: MyList indices must be positive

Upvotes: 1

Adriano Martins
Adriano Martins

Reputation: 1808

If you are just creating a list within a list, there is no need to use classes:

def map2d(x, y):
    return [[None for _ in range(y)] for _ in range(x)]

print(map2d(3, 2)) # [[None, None], [None,None], [None,None]]

This will give you the desired output.

Also, note that if you are looking to customize the way a class is printed, you should use the method __str__, eg:

class Example:
    def __str__(self):
        return "Example Class Object"

print(Example()) # Example Class Object

Upvotes: 1

Related Questions