Is there a pythonic way of referring to the current object (self-reference) we are declaring with (some) Pythons built-in types?

Viewed 154

With (some) Pythons built-in types, is it possible to refer to the object we are declaring ? By "(some) built-in types" I think about, for example, sequence types, mapping types or set types, obviously not numeric types.

I mean, without creating a class myself and adding this functionality (without creating a subclass).

So, something like the this keyword as used in the examples below.

For example, for the "dict" Python built-in type, something like this:

a_dictionary = {
    "key_1": "value_1",
    "key_2": "value_2",
    "key_3": this["key_1"] + "_" + this["key_2"] # == "value_1_value_2"
}

or even:

a_dictionary = {
    "sub_dict_1": {
        "key_1": "value_1_1",
        "key_2": "value_1_2",
        "key_3": this["key_1"] + "_" + this["key_2"] # == "value_1_1_value_1_2"
    },
    "sub_dict_2": {
        "key_1": "value_2_1",
        "key_2": "value_2_2",
        "key_3": this["key_1"] + "_" + this["key_2"] # == "value_2_1_value_2_2"
    }
}

I've read :

When doing function chaining in python, is there a way to refer to the "current" object?

What do I do when I need a self referential dictionary?

Reference a dictionary within itself

Self-referencing classes in python?

Is there a way to refer to the current function in python?

Is it possible to access current object while doing list/dict comprehension in Python?

and some others, but it doesn't match up the requirements described at the begining of my question.

Thanks a lot for your help!

2 Answers

Python provides no way to refer to an object under construction by a literal or a display*. You can (ab)use the assignment expression in Python 3.8 or later to simulate this:

a_dictionary = {
    "key_1": (x := "value_1"),
    "key_2": (y := "value_2"),
    "key_3": x + "_" + y 
}

It requires some planning ahead, as you are not referring to a key value directly, rather a pre-defined variable. Notice that x and y remain in scope after the assignment to a_dictionary, so this is just a questionable equivalent of

x = "value_1"
y = "value_2"
a_dictionary = {
    "key_1": x,
    "key_2": y,
    "key_3": x + "_" + y
}

A custom class would really be more appropriate:

class Thing:
    def __init__(self, v1, v2):
        self.key_1 = v1
        self.key_2 = v2
        self.key_3 = v1 + "_" + v2


a_thing = Thing("value_1", "value_2")

  • A display is a construct like a literal, but could contain non-literal references. For example, list displays include [1, x, y] and [int(x) for x in foo].

After some digging, and only for the case of a dictionary, I found this other workaround, based on What do I do when I need a self referential dictionary? :

class MyDict(dict):
    def __getitem__(self, item):
        return dict.__getitem__(self, item).format(self)

a_dictionary = MyDict({
    "key_1": "value_1",
    "key_2": "value_2",
    "key_3": "{0[key_1]}" + "_" + "{0[key_2]}" # == "value_1_value_2"
})
Related