On 2/11/21 1:43 PM, Greg Ewing wrote:
On 12/02/21 7:05 am, Andras Tantos wrote:

     a = B()
     a.m(41)
     a.m = MethodType(method, a)
     a.m(42)

Are you sure you really need to inject methods into instances
like this? What problem are you trying to solve by doing so?
There's almost certainly a better way to approach it.

Greg,

This is going to be a long a convoluted story, but since, you've asked...

I'm developing a library to describe hardware (RTL) in Python and convert it into Verilog (or potentially other languages).

In this project, I have two concepts:

1. Ports, which are the connection points on the various netlist entities. These would be the inputs and outputs of an AND gate for example

2. NetTypes, which describe the type of data that can travel through a net (and thus through a Port). One such type would be an 8-bit signed integer, or a simple logic signal.

There are derived types of the Port object (for inputs and outputs etc.) as well as of NetType (for signed integers, structs, etc.)

An interesting aspect of the problem is that most ports don't need to have a type initially: it can be deduced from the connectivity (netlist) of the circuit described. So, for example the above mentioned AND gate can handle any input as long as they are of the same NetType and produce an output of the same NetType. This is to say, that Ports have an optional NetType, the association between Port and NetType is dynamic and changes during the lifetime of the Port instance.

There are two ways I can think of modelling this in Python:

1. A (derived) Port instance uses multiple-inheritance to also inherit from it's (derived) NetType

2. A (derived) Port instance has a member of a (derived) NetType instance

I went with #2 in my current implementation.

Now, when a Port gets assigned a NetType, it needs to gain all sorts of new features. It for example should have a 'length' attribute that tells how many bits are needed to represent its possible values. The list of these new features (attributes, methods, properties) are known to the NetType and should be injected into the Port when the NetType is assigned to the Port.

With #1, the situation is different, but not any less complicated: now, the features are automatically appear in the Port instance (maybe even too much so) but we dynamically mess with the inheritance tree of the type of the Port instance.

The example I've written up deals with the problems when I try to inject these new features into the Port instance (say a new method) and the method implementation intends to call back the base-class behavior for some reason.

I believe even #1 could have similar problems in different ways though: since I manipulate the inheritance chain dynamically, I don't think there's a guarantee that the statically determined '__class__' cell will be the same as the dynamically expected one.

Andras


--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to