2

Working further with the Dill package. Posted yesterday exemplifying some ignorance of referents, referrers, inheritance and containers. The answer was insightful, but I'm still having trouble coming up with examples that show a few levels of depth in referrer and referent chains.

Yesterday I was thinking that an instance would be a referrer to it's class. In the Dill docs children are the referrers, so in that case a child of depth=2 would be a grandchild, right? And would that be an object that refers (points) to another object that refers to another object?

What would be an example of an object that has a chain of referents and referrers of at least a depth of two?

Consider:

 import dill

class GreatGrandparentClass(object):
    """A Great Grandparent class"""

    name = "Henrietta Ancient One"

class GrandparentClass(GreatGrandparentClass):
    """A Grandparent class"""

class ParentClass(GrandparentClass):
    """A Grandparent class"""

great_grand_parent = ParentClass().name

print ("Children (depth=2):")

for element in dill.detect.children(
                        great_grand_parent, 
                        list, 
                        depth=2, 
                        ignore=(globals())):
    print(element)

print ("Parents:")
for element in dill.detect.parents(                        
                        great_grand_parent, 
                        list, 
                        depth=2, 
                        ignore=(globals())):
    print(element)

returns:

Children (depth=2):
['\npython pydill.py\n\n', 'dill', 'object', 'A Great Grandparent class', 'i', 'Henrietta Ancient One', 'GreatGrandparentClass', 'GreatGrandparentClass', 'A Grandparent class', 'GrandparentClass', 'GrandparentClass', 'A Grandparent class', 'ParentClass', 'great_grand_parent', 'ParentClass', 'i', 'Children (depth=2):', 'element', 'dill', 'detect', 'children', 'great_grand_parent', 'list', 'depth', 2, 'ignore', 'globals', 'element', 'Parents:', 'element', 'dill', 'detect', 'parents', 'great_grand_parent', 'list', 'depth', 2, 'ignore', 'globals', 'element']
Henrietta Ancient One
Parents:
Henrietta Ancient One

Looking specifically at list objects here, the single referrent (Parent) of great_grand_parent is the string, "Henrietta Ancient One".

And the referrers (Children) (result of gc.get_referrers(), filtered by specified object-type) contains two objects: A list that includes the string 'Henrietta Ancient One', and the string Henrietta Ancient One. (depth=2 and depth=1 return the same result.)

How can I make an object for which Dill can return:

  1. Two distinct depths of referrers
  2. Two distinct depths of referents
Community
  • 1
  • 1
MikeiLL
  • 6,282
  • 5
  • 37
  • 68

1 Answers1

1

Here's an example of children and parents, that may be a little surprising at first if you aren't familiar with how python builds class instances...

We construct a class, and will try to get at the method foobar from the instance of the class.

>>> class Dummy(object):
...   def foobar(self, x):
...     return x**2 + 1
... 
>>> me = Dummy()
>>> import types
>>> dill.detect.parents(me, types.MethodType, depth=2)
[<__main__.Dummy object at 0x105173890>]
>>> dill.detect.parents(me, types.FunctionType, depth=2)
[<__main__.Dummy object at 0x105173890>]

It seems to not be working… but actually, it's due to how python builds class instances. It turns out, class instances point to classes... but from there, the class instances utilize the class __dict__ to lookup any of the class methods or attributes. Thus, any contained methods or functions are at depth=3 (not depth=2).

>>> dill.detect.parents(me, types.FunctionType, depth=3)
[<__main__.Dummy object at 0x106b94750>, <class '__main__.Dummy'>, {'__dict__': <attribute '__dict__' of 'Dummy' objects>, 'foobar': <function foobar at 0x106b8ed70>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Dummy' objects>, '__doc__': None}, <function foobar at 0x106b8ed70>]

Now, going the other way is very much in line with what you were thinking about using class inheritance.

>>> class Dummy2(Dummy): 
...   pass
... 
>>> alsome = Dummy2()
>>> dill.detect.children(Dummy, type(alsome), depth=2)
[<__main__.Dummy2 object at 0x105d6d390>, <class '__main__.Dummy2'>, <class '__main__.Dummy'>]
Mike McKerns
  • 33,715
  • 8
  • 119
  • 139