Auto-Vivification in Python

We saw in the earlier post what is auto-vivification and how we can implement it in JavaScript.
Can we do it in Python as well? Yes, Sure.

Python does not have built in auto-vivification

Let's see if it supports it
univ = {}
univ.college.stream.year = 1
''' Output
univ.college.stream.year = 1
AttributeError: 'dict' object has no attribute 'college'
'''
view raw NoAutoViv.py hosted with ❤ by GitHub
No AutoViv in Python

Nope!
So what can we do?
Well, Python is a dynamic language, which allows us not only to add properties (attributes) at runtime but we can also ‘intercept’ calls to attributes which do not exist.

class Univ:
def __init__(self):
# define an attribute
self.name = "ABC"
univ = Univ()
print(univ.name) # This works
print(univ.college) # This gives error
view raw NoAttrib.py hosted with ❤ by GitHub
No Attribute Error

So, can we intercept univ.college access and do something different? Sure

class Univ:
def __init__(self):
self.name = "ABC"
# This gets called when attribute is missing
def __getattr__(self, attribute):
try:
return self[attribute]
except:
return "We are very sorry, we cannot server you that yet"
univ = Univ()
print(univ.name) # Actual attribute
print(univ.college) # Custom response
''' Output
ABC
We are very sorry, we cannot server you that yet
'''
Intercept Attribute

Great, we can intercept calls for missing attributes, but can we create the attribute on the fly? Sure

Magic of dunders ( double underscores)
Here we override __getattr__/__setattr__ for univ.college.stream.year = “A+”
and we override __getitem__ for univ[‘college’][‘stream’][‘year’] = “A+”

auto inherits a dictionary

This way we can store the attributes in “dict” we are inheriting which simplifies our code to bare minimum. We can also show “bravado” and build this WITHOUT inheriting from dict and manage everything ourselves. Perhaps, another blog post?

Over to final code
# auto inherits a dictionary
class auto(dict):
# if caller did univ.college
def __getattr__(self, name):
try:
# check if its there
return dict.__setitem__(self, name)
except:
# if not, create it on the fly
dict.__setitem__(self, name, auto())
return dict.__getitem__(self, name)
# if caller did univ.college = value
def __setattr__(self, name, value):
# set it in internal dict
dict.__setitem__(self, name, value)
# if caller did univ['college]
def __getitem__(self, value):
try:
# if found return it
return dict.__getitem__(self, value)
except:
# if not, create it on the fly
dict.__setitem__(self, value, auto())
return dict.__getitem__(self, value)
univ = auto()
univ.college.stream.year = "A+"
print(univ)
univ2 = auto()
univ2['college']['stream']['year'] = "A+"
print(univ2)
view raw AutoViv.py hosted with ❤ by GitHub
Auto Vivification in Python
And here is the output
univ1 {'college': {'stream': {'year': 'A+'}}}
univ2 {'college': {'stream': {'year': 'A+'}}}

Auto Vivification Series

  1. Auto vivification in JavaScript
  2. Auto vivification in Python
  3. Auto vivification in JavaScript (Upgraded)

Auto-Vivifaction in JavaScript

What? You mean auto-verification? NO!

Vivification is when we directly assign a deeply nested attribute/property while the ones above don’t exist, and yet the entire hierarch is automatically created.

Take example of *nix mkdir command. It creates a new directories in a given directory

# Create a single directory in current directory
$ mkdir temp
$ tree
.
└── temp

But, we can also create sub-sub-sub directory

# Try to create a nested directory
# When outer ones don't exist
$ mkdir faltu/bakwaas/bekaar

mkdir: faltu/bakwaas: No such file or directory

See, no vivification! We are unable to create bekaar directory because faltu and bakwaas don’t exist.
We will be forced to create parent directories before the child and grandchild.

# Sigh! One at at ime
$ mkdir faltu
$ mkdir faltu/bakwaas
$ mkdir faltu/bakwaas/bekaar
$  tree
.
└── faltu
    └── bakwaas
        └── bekaar

Don’t we wish we could directly create bekaar without creating faltu and bakwaas first?
Welcome to Auto-vivification. Automatic creation of outer structure when directly creating a nested structure.

# Vivification in mkdir (watch the p)
$ mkdir -p good/bad/ugly
$ tree
.
└── good
    └── bad
        └── ugly

So now we understand auto-vivification, can we do this in programming languages as well?
Well, *some* of them, like perl

perl lnaguage has support auto-vivification. We can directly assign to $year and it would automatically create the chain of $college and $stream

my $univ;
my $college="SITS";
my $stream="BECS";
my $year=4;

$univ{$college}{$stream}{$year}="A+";
print($univ{$college}{$stream}{$year});

Let's do it in JavaScript
// No auto-vivification in JavaScript

// Create top level object
let univ = {};

// Now assign to a deeper level
univ.college.stream.year = "A+"; // ERROR

--------------------------------------------
Output
--------------------------------------------
univ.college.stream.year = "A+"; // ERROR
             ^

TypeError: Cannot read property 'stream' of undefined

Yep, that’s right. While we have an object called univ, currently we do not have a property called ‘college’ and ‘stream’ while trying to assign value to ‘year’

Let’s understand the problem first. When we try to assign to a nested property in JavaScript, it tries to “get” the parent property, which does not exist and we get an error.

How about if we intercept that and create the parent property on-the-fly? Hmm…

let univ = {
  // If property exists return it
  // Otherwise, create it and return it
  get: (prop) => { 
    this[prop] 
      ? this[prop] 
      : this[prop] = {} }
}

univ.college = "SITS"; // WORKS!!!
console.log(univ);

univ.college.stream.year = "BECS"; // ERROR
console.log(univ); 

Well, our joy was short-lived. While it can create any property on the fly inside univ
univ.college = "ABCD";
univ.establised = 1884;
univ.name = "Amazing";

but we cannot do it at the next level, so this doesn’t work
univ.college.stream = "CS";

JavaScript Proxy object to the rescue!
A Proxy object plugs-in another object and can be handler for certain functions/properties.
E.g. We can have a Proxy object which handles get for the handled object.

// Use Proxy object and handler to create a new property on the fly
let AutoViv = () =>

  // Proxy() object of JavaScript
  new Proxy({}, // ANY blank object
    {
      // if property exists, return it
      // Otherwise, create it
      get: (obj, prop) => 
        prop in obj 
          ? obj[prop] 
          : obj[prop] = AutoViv()
    }
  )
Time to put this to test!
// Use Proxy object and handler to create a new property on the fly
let AutoViv = () =>

  // Proxy() object of JavaScript
  new Proxy({},
    {
      // Handler checks if prop does not exists, creates it
      get: (obj, prop) => 
        prop in obj 
          ? obj[prop] 
          : obj[prop] = AutoViv()
    }
  )

// Create only TOP level
let univ = AutoViv();

// Now assign to deeper level
univ.college.stream.year = "A+";
console.log("univ", univ);

let univ2 = AutoViv();
univ2['college']['stream']['year'] = "A+";

// Bingo! It works
console.log("univ2", univ2);

Output
univ { college: { stream: { year: 'A+' } } }
univ2 { college: { stream: { year: 'A+' } } }

Congratulations! We have an Auto-Vivification object in JavaScript now, which allows us to create a nested property without first defining its parent property!

Can we do it in other languages too? Maybe next post.. AutoVivification in Python

Auto vivification Series

  1. Auto vivification in JavaScript
  2. Auto vivification in Python
  3. Auto vivification in JavaScript (Upgraded)