Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to override the assignment ('=') operator in Python?

Is there a dunder for this? Perhaps something along the lines of: (updated)

class Tree:
    def __init__(self, item_or_tree):
        self._setto(item_or_tree)

    def __assign__(self, val):
        self._setto(item_or_tree)

    def __setitem__(self, which, to_what):
        ## I would like this to call __assign__ on the Tree object at _tree[which]
        to_what._tree[which] = to_what

    def __getitem__(self, which):
        return self._tree[which]

    def __len__(self): return len(self._tree)

    def __eq__(self, other):
        if isinstance(other, Tree):
            if other._is_tree:
                return (self._item == other._item) and (self._tree == other._tree)
            else:
                return self._item == other._item
        else: return self._item == other

    def _setto(self, item_or_tree):
        if isinstance(item_or_tree, Tree):
            self._set_from_Tree(item_or_tree)
        elif isinstance(item_or_tree, dict):
            self._set_from_dict(item_or_tree)
        else:
            self._set_from_other(item_or_type)


    def _set_from_Tree(self, other_Tree):
        self._tree = other_Tree[:]
        self._item = other_Tree
        self._is_tree = other_Tree._is_tree

    def _set_from_dict(self, the_dict):
        self._is_tree = True
        self._item = None
        self._tree = {}
        for key, val in the_dict.items():
            self._tree[key] = Tree(val)

    def _set_from_other(self, other):
        self._is_tree = False
        self._tree = None
        self._item = other

class TreeModel(Tree, QAbstractItemModel):
    ...
    ## a whole bunch of required overrides
    ## etc
    ...

What I'm trying to do is implement a generalized tree structure that acts as intuitively (to me) as possible and also seamlessly integrates with PyQt5's Model-View-Delegate architecture.

I want to be able to set the incoming item_or_tree to either the item or tree. So I'm looking to overload the function that's called when the = operator is used on the item.

PyQt has this item based architecture in which a QAbstractItemModel is overridden. This is (I guess) supposed to return / accept QModelIndex objects. These are trees of tables (2D arrays).

So I'm creating a single tree structure that can contain itself, deal with the 2 opposing indexing paradigms, and plays nice with Python and everything else.

like image 651
Inversus Avatar asked Aug 22 '14 22:08

Inversus


People also ask

Can assignment operator be overridden?

You can overload the assignment operator (=) just as you can other operators and it can be used to create an object just like the copy constructor.

Can you override operators in Python?

We can overload all existing operators but we can't create a new operator. To perform operator overloading, Python provides some special function or magic function that is automatically invoked when it is associated with that particular operator.

How do you overload an assignment operator?

Overloading the assignment operator (operator=) is fairly straightforward, with one specific caveat that we'll get to. The assignment operator must be overloaded as a member function. This will call f1. operator=(f1), and under the simplistic implementation above, all of the members will be assigned to themselves.

Is overloading possible in Python?

Like other languages (for example, method overloading in C++) do, python does not support method overloading by default.


1 Answers

It is not possible to override the implementation of x = y. See Facts and Myths about Python Names and Values for details of what assignment means.

You can override x.a = y, with __setattr__, it is (roughly) x.__setattr__('a', y).

You can override x[k] = y with __setitem__, it is (roughly) x.__setitem__(k, y).

But you can't override x = y.

like image 51
Ned Batchelder Avatar answered Sep 20 '22 16:09

Ned Batchelder