1

So I have in my project two classes: Circuit and SubCircuit. At some point I may need to construct a SubCircuit from a Circuit. Is there a more elegant way to do that than what's done below in the last 4 lines? Circuit may get some new attributes at some point for example, which would mean that conversion would also need to be updated - basically inviting bugs.

class Gate(abc.ABC):
    def __init__(self, size):
        self.in_ports = (InPort(self),) * size
        self.out_ports = (OutPort(self),) * size


class Circuit:
    def __init__(self, size):
        self.input = (OutPort(self),) * size
        self.output = (InPort(self),) * size
        self.gates = []

    # ... some other stuff that messes around with these attributes


class SubCircuit(Gate, Circuit):
    def __init__(self, circuit=None):
        Gate.__init__(self, size)
        Circuit.__init__(self, size)

        if circuit is not None:
            self.gates = circuit.gates
            self.input = circuit.input
            self.output = circuit.output

1 Answer 1

1

Bugs are already there - when you do self.gates = circuit.gates, circuit.gates being a list, yu point both references to the same list - and if this list is updated on the original circuit, this update will be reflected in your subcircuit instance.

I think the most sane pattern tehre is to have an alternate constructor for the class if you have a circuit instance from which to update your own:

from copy import copy
class SubCircuit(Gate, Circuit):
    def __init__(self, size):
        Gate.__init__(self, size)
        Circuit.__init__(self, size)

    @classmethod
    def from_circuit(cls , circuit, size):
        self = SubCircuit(size)
        for key, value in circuit.__dict__.items():
             setattr(self, key, copy(value))
        return self

One "right" thing to do is to make the classes __init__ and other methods calling each other through the collaborative use of super() instead of calling then explicitly by name - however, if your classes and subclasses are fixed to these 3, that may be a bit overkill, because Python's objects not handling extra parameters passed to its own __init__ method. (So, you'd have to verify in your base classes __init__ if they are the last ones prior to object on the Method Resolution Order, and swallow the remaining args)

Sign up to request clarification or add additional context in comments.

3 Comments

That behaviour sounds like something I would want - if the original circuit is edited, the subcircuit component that represents it in another circuit should be edited as well. Is there a reason to consider this a bug immediately?
No - it that is the desired result, just throw away all mentions to "copy" - it is just that one might find it to be unexpected.
Then you could just do self.__dict__.update(circuit.__dict__) instead of the for loop in the liens [-:3-1] above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.