views:

52

answers:

1

Yesterday I asked ("A case of outwardly equal lists of sets behaving differently under Python 2.5 (I think …)") why list W constructed as follows:

r_dim_1_based = range( 1, dim + 1)
set_dim_1_based =  set( r_dim_1_based)

def listW_fill_func( val):
    if (val == 0):
        return set_dim_1_based
    else:
        return set( [val])

W = [ listW_fill_func( A[cid])  
            for cid in r_ncells ]

didn't behave as I expected. In particular, it did not behave like other lists that showed equality with it (another_list == W --> True).

Is there a utility, trick, builtin, whatever that would have shown these differing internal structures to me? Something that would have produced perhaps a C-like declaration of the objects so that I would have seen at once that I was dealing with pointers in one case (list W) and values in the others?

+1  A: 

You're dealing with references in each case (more similar to pointers than to values). You can surely introspect your objects' references to your heart's contents -- for example, if you have a list and want to check if any items are identical references,

if len(thelist) != len(set(id(x) for x in thelist)): ...

DO note that we're talking about references here -- so, two identical references to None, or two identical references to the int value 17, would also trigger the same alarm. Of course you can keep introspecting to remove that case, eliminating immutables from the list in a first pass, for example, if you think that multiple references to the same immutable are fine -- e.g.:

immutyps = int, long, float, tuple, frozenset, str, unicode
mutables = [x for x in thelist if not isinstance(x, immutyps)]
if len(mutables) != len(set(id(x) for x in mutables)):
  cryhavocandletloosethedogsofwar()

but I would question the return-on-investment of such a deep introspection strategy!

Alex Martelli
Hi again, Alex. I was wondering if there was some easy way to feed an object to a little engine and get back a graph or something C-declaration-like that showed what the architecture of the object. Referring to yesterday's example, if I'd fed lists W1, W2, and W3 to the 'engine', I would have seen that in W3, all the "unknown" items were references (pointers) to the same variable, whereas in lists W1 and W2, those items were really the independent sets that I imagined them to be.
behindthefall
Ack. How do I edit a comment? Stick a verb at the end of that first sentence.
behindthefall
But I have to say that your first statement is a keeper, and I will try to remember id().
behindthefall
@behindthefall, the only way I know to "edit a comment" in SO is: copy it, delete it, make a new comment, paste what you copied it, edit, click "add comment". Anyway, sure, you can make graphs out of your objects' internal structures, though I'm not sure what you mean with "C-declaration-like" -- what C declaration would you like for, e.g., `[[], []]*2` vs `[[], [], [], []]`? If you're asking for existing modules that would turn these into graphs (much less C-like declarations, whatever that means), I don't know of any, sorry.
Alex Martelli
Don't you ever wish you had an easy way to see what was going on beneath the hood, beyond what _repr_() and == tell you?
behindthefall
Once I got used to reading them, I grew quite fond of C declarations. I've always thought that SGML and all its spawn could have profited from their expressiveness and economy. However, it's been years since I've written C, so I'm not going to come up with examples off the top of my head. (Sorry.) BTW, I just tried printing out the id()s of items in "equal" lists constructed by different methods, and those identical refs to a single variable stand out. Good trick. Thanks
behindthefall
I find the existing introspection abilities quite adequate, but that may be because I don't really find myself "debugging" data structures. Wrt declarations, they don't carry values (otherwise they'd be definitions!), so I don't see how seeing something declared as `foo* x` helps understanding _where_ `x` points. But `id` is basically the memory address of an object (or any other unique identifier thereof, but in practice it's the address in current Python) so it can surely help identification issues!
Alex Martelli