Python Forum
Syntax to print ndarray member of class containing ndarray - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Syntax to print ndarray member of class containing ndarray (/thread-28165.html)



Syntax to print ndarray member of class containing ndarray - pjfarley3 - Jul-08-2020

If I define a class Q containing a member which is an ndarray of strings, I can print that class member by name.

If I define another class G containing a member which is an ndarray of class Q objects, what syntax do I use to print all the actual contents of the contained class Q members and not "<__main__.Q object at ....>"?

Python 3 example and output follow.

TIA for any help you can provide to cure my ignorance.

Peter

import numpy as np
class Q:
    def __init__(self,qsize):
        self.qs = qsize
        self.s = np.full([qsize, qsize], " . ", dtype='<U3')


class G:
    def __init__(self, gsize, gval):
        self.gs = gsize
        self.g = np.full([gsize, gsize, gsize], gval, dtype=Q)


qsz = 2
qx = Q(qsz)
print("Created gx = Q()")
print(qsz, qx.qs, qx.s)

gsz = 2
gx = G(gsz, qx)
print("Created gx = G(qx)")
print(gsz, gx.gs, gx.g)
print(gsz, gx.gs, gx.g.s)
Output:

Output:
Created gx = Q() 2 2 [[' . ' ' . '] [' . ' ' . ']] Created gx = G(qx) 2 2 [[[<__main__.Q object at 0x000002538DD74CA0> <__main__.Q object at 0x000002538DD74CA0>] [<__main__.Q object at 0x000002538DD74CA0> <__main__.Q object at 0x000002538DD74CA0>]] [[<__main__.Q object at 0x000002538DD74CA0> <__main__.Q object at 0x000002538DD74CA0>] [<__main__.Q object at 0x000002538DD74CA0> <__main__.Q object at 0x000002538DD74CA0>]]] Traceback (most recent call last): File "clstest.py", line 25, in <module> print(gsz, gx.gs, gx.g.s) AttributeError: 'numpy.ndarray' object has no attribute 's'



RE: Syntax to print ndarray member of class containing ndarray - ndc85430 - Jul-08-2020

You need to implement __str__ in your class. See, e.g. the docs.


RE: Syntax to print ndarray member of class containing ndarray - pjfarley3 - Jul-08-2020

Implement __str__ in which class, Q or G? In the contained class or the containing class?

Why wouldn't the __str__ method of class Q (or perhaps the one inherited from ndarray?) which obviously works because I can print qx.s also work for gx.g.s?

I guess you are saying that the default __str__ of ndarray does not know how to interpret objects of type ndarray? Why not? It would seem to me a simple case of recursion - "Look there, my elements are my own type, let me invoke myself to interpret them".

Peter


RE: Syntax to print ndarray member of class containing ndarray - ndc85430 - Jul-09-2020

(Jul-08-2020, 02:10 PM)pjfarley3 Wrote: Implement __str__ in which class, Q or G? In the contained class or the containing class?

In Q if you want a custom string representation of those objects

Quote:Why wouldn't the __str__ method of class Q (or perhaps the one inherited from ndarray?) which obviously works because I can print qx.s also work for gx.g.s?

qx.s is not an instance of Q, is it? It's an instance of ndarray. gx.gs is not an instance of Q either; it's an int. The __str__ method that exists on Q is obviously the one you inherit from object, which is giving you the default string representation that you're seeing. If you print(qx), you'll see the same thing.


RE: Syntax to print ndarray member of class containing ndarray - pjfarley3 - Jul-09-2020

Isn't there some form of list comprehension that can be used as simply as I can print(qx.s) to print(gx.g.s)?

I can obviously set up nested for loops and concatenate formatted strings into an initially null string and finally print the concatenated string, but this seems very un-pythonic.

Isn't there a better way than the following to do thie?

Peter

import numpy as np
class Q:
    def __init__(self,qsize):
        self.qs = qsize
        self.s = np.full([qsize, qsize], " . ", dtype='<U3')


class G:
    def __init__(self, gsize, gval):
        self.gs = gsize
        self.g = np.full([gsize, gsize, gsize], gval, dtype=Q)


qsz = 2
qx = Q(qsz)
print("Created qx = Q()")
print(list(np.shape(qx.s)))
print([x for x in np.shape(qx.s)])
print(qsz, qx.qs, qx.s)

gsz = 2
gx = G(gsz, qx)
print("Created gx = G(qx)")

print(gsz, gx.gs, gx.g)
print("shape(gx.g):", np.shape(gx.g))

pstr = ""
for x in range(gsz):
    for y in range(gsz):
        for z in range(gsz):
            pstr += "{},".format(gx.g[x,y,z].s)
print(pstr)            
Output:
Created qx = Q() [2, 2] [2, 2] 2 2 [[' . ' ' . '] [' . ' ' . ']] Created gx = G(qx) 2 2 [[[<__main__.Q object at 0x000001DB203C10D0> <__main__.Q object at 0x000001DB203C10D0>] [<__main__.Q object at 0x000001DB203C10D0> <__main__.Q object at 0x000001DB203C10D0>]] [[<__main__.Q object at 0x000001DB203C10D0> <__main__.Q object at 0x000001DB203C10D0>] [<__main__.Q object at 0x000001DB203C10D0> <__main__.Q object at 0x000001DB203C10D0>]]] shape(gx.g): (2, 2, 2) [[' . ' ' . '] [' . ' ' . ']],[[' . ' ' . '] [' . ' ' . ']],[[' . ' ' . '] [' . ' ' . ']],[[' . ' ' . '] [' . ' ' . ']],[[' . ' ' . '] [' . ' ' . ']],[[' . ' ' . '] [' . ' ' . ']],[[' . ' ' . '] [' . ' ' . ']],[[' . ' ' . '] [' . ' ' . ']],

(Jul-09-2020, 04:58 AM)ndc85430 Wrote:
(Jul-08-2020, 02:10 PM)pjfarley3 Wrote: Implement __str__ in which class, Q or G? In the contained class or the containing class?

In Q if you want a custom string representation of those objects

Quote:Why wouldn't the __str__ method of class Q (or perhaps the one inherited from ndarray?) which obviously works because I can print qx.s also work for gx.g.s?

qx.s is not an instance of Q, is it? It's an instance of ndarray. gx.gs is not an instance of Q either; it's an int. The __str__ method that exists on Q is obviously the one you inherit from object, which is giving you the default string representation that you're seeing. If you print(qx), you'll see the same thing.

Thanks for that reply, and I do understand that asking to print an entire Q object as a whole requires a __str__ method in Q. But I am only asking to print the "s" components of the ndarray of Q objects gx.g, or in my naive way gx.g[].s or some equivalent syntax.

Shouldn't the s component of the ndarray of Q objects be printable in some simple manner not involving for loops?

Peter


RE: Syntax to print ndarray member of class containing ndarray - ndc85430 - Jul-09-2020

(Jul-09-2020, 05:16 AM)pjfarley3 Wrote: Isn't there some form of list comprehension that can be used as simply as I can print(qx.s) to print(gx.g.s)?

Quote:But I am only asking to print the "s" components of the ndarray of Q objects gx.g, or in my naive way gx.g[].s or some equivalent syntax.

Remember that ndarray objects can contain objects of basically any other type, so it's up to the programmer to know what type is in them and how to deal with them. Therefore, you have to go over all of the items and do your printing as you are, or transform the ndarray of Qs into an ndarray of whatever type Q.s is. With Python lists, you'd use map or, like you say, a list comprehension to do that transformation, but I don't know the API for ndarray well enough to know which method to use (there doesn't seem to be a map).


RE: Syntax to print ndarray member of class containing ndarray - pjfarley3 - Jul-09-2020

(Jul-09-2020, 05:37 AM)ndc85430 Wrote: Remember that ndarray objects can contain objects of basically any other type, so it's up to the programmer to know what type is in them and how to deal with them. Therefore, you have to go over all of the items and do your printing as you are, or transform the ndarray of Qs into an ndarray of whatever type Q.s is. With Python lists, you'd use map or, like you say, a list comprehension to do that transformation, but I don't know the API for ndarray well enough to know which method to use (there doesn't seem to be a map).

Thanks for the advice. I'm going to have to chew on that for a while and do some more RTFM. I discovered numpy.nditer for iterating over an ndarray, but there are issues specifying just the Q.s member of each element of the gx.g ndarray while ignoring the Q.qs member.

I'll reply again after I do more research.

Peter