I think I can learn a lot from any answer to the two questions in this post.

OK, I’ve got a large object. That object has attributes and does things.

Those attributes also do things. MOST of what they do is sit there like a list, int, or np.array and wait to tell something else what to do. BUT SOMETIMES, they’ve got to do something on their own.

So, I can’t do, for instance

if method.attribute == something:

I’ve got to instead do

If method.attribute.value == something:

I can get around this with lists or ints by making a class with a “default” value and additional methods:

class Int(int):pass

But I can’t do that with arrays, so I sometimes end up with ugly stuff like

if method.attribute.value(key).value == something:

So, two questions:

Have I gone completely wrong?

If not, what is the canonical way to guard against initializing a new instance with

NewInstance = ClassName(OldInstance, *args)

when I meant

NewInstance = ClassName(OldInstance.value, *args)

Right now, I’m doing something like

class ClassName(object):
def __init__(self, value, *args):
        self IsClassNameInstance = True
        if hasattr(value, ‘IsClassNameInstance’):
            raise # some error

Thank you.

Could you give short example with one type and some values to show what you are really doing, I do not understand. (So otherwise I would say you are completely wrong, but I am not really OO expert)

Thanks for the reply. Here's an example:

A Mesh object storing and manipulating Points, Edges, and Faces in a half-edge data structure.

The Mesh object stores mesh data as a dict of Points, a dict of Edges, and a dict of Faces. Let's just talk about the dict of Points (call it PDict).
Each Point in PDict is a numpy.array describing a location in 3D space. One of the methods which acts upon these Points must examine all Mesh data then select and combine some of the Points, so I create a method, combine, of Mesh which examines Edges and Faces and selects and combines certain Points in PDict. The selection of Points is described in vombine. The combination of Points is simple:

(PDict[0]+PDict[1])/2.

no method required.

So, the furthest I need to reach into my object is

MeshInst.PDict[0]

Textbook OOP in my limited understanding.

BUT, say I want to assign some characteristics to each Point. Now, each Point has to go from /being/ a np.array to /having/ a np.array. Now, I have to reach a little deeper to get to the location of a Point

MeshInst.PDict[0].location

And the combination of points is no longer simple. I've got to combine the points /and/ their characteristics in a combine method within my point class.

And the combination of each characteristic is not simple, either. So each characteristic /has/ an int or /has/ a list or /has/ an array along with its own combine method.

Now, if I must reach a Point characteristic from Mesh, I have to

MeshInst.PDict[0].PointAttr.value

And it just gets uglier from there, which is why I suspect I'm doing something wrong. This should be an ideal OOP task, but the procedural version (tests make adding new Point characteristics easy) comes out simpler.