The method is ignored when subclassing the type defined in module C

I will subclass the type defined in the C module for the alias of some attributes and methods so that my script works in different contexts.

How to do this to work, I need to manually configure the dictionary of my class? If I do not add a link to DistanceTo in dictionnary, I get Point3d has no attribute named DistanceTo .

 class Point3d(App.Base.Vector): def __new__(cls, x, y, z): obj = super(Point3d, cls).__new__(cls) obj.x, obj.y, obj.z = x, y, z obj.__dict__.update({ 'X':property(lambda self: self.x), 'Y':property(lambda self: self.y), 'Z':property(lambda self: self.z), 'DistanceTo':lambda self, p: self.distanceToPoint(p)}) return obj def DistanceTo(self, p): return self.distanceToPoint(p) 

I thought that as soon as __new__ returned the instance, I could still populate it with methods and attributes. Can anyone shed some light on this?

EDIT: The module I'm importing from is FreeCAD. Base type C is defined there . Then the Vector is derived from this definition here

EDIT2: I also tried the following:

 class Point3d(App.Base.Vector): def __new__(cls, x, y, z): obj = super(Point3d, cls).__new__(cls) obj.x, obj.y, obj.z = x, y, z obj.__dict__.update({ 'X': x, 'Y': y, 'Z': z, 'DistanceTo':lambda self, p: self.distanceToPoint(p)}) return obj def DistanceTo(self, p): return self.distanceToPoint(p) 

and after creating the second point, as Point3d p returns the value of the last point for pX , pY and pZ regardless of what parameters x,y,z were passed when creating the instance. px, py, pz return the expected values. It seems that the dictionary is shared between instances.

EDIT 3: Problem solved! The Py_TPFLAGS_BASETYPE bit is set to zero to prevent subclassing, as described in the answer below.

+5
source share
2 answers

I found the answer in PyObjectBase.cpp :

 /** \brief * To prevent subclasses of PyTypeObject to be subclassed in Python we should remove * the Py_TPFLAGS_BASETYPE flag. For example, the classes App::VectorPy and App::MatrixPy * have removed this flag and its Python proxies App.Vector and App.Matrix cannot be subclassed. * In case we want to allow to derive from subclasses of PyTypeObject in Python * we must either reimplment tp_new, tp_dealloc, tp_getattr, tp_setattr, tp_repr or set them to * 0 and define tp_base as 0. */ 

This is because the App::VectorPy not implemented to safely support the subclass, so the Py_TPFLAGS_BASETYPE bit is set to zero to prevent it.

For information, this is a similar situation with the built-in type bytes , which cannot be subclassed. See the discussion to hear from Guido van Rossum why bytes not a subclass.

+1
source

I do not understand why you want to add properties dynamically. Just use:

 class Point3d(App.Base.Vector): def __init__(self, x, y, z): super().__init__(x, y, z) # or maybe super().__init__([x, y, z]) @property def X(self): return self[0] # guessing that App.Base.Vector works like a list @property.setter def X(self, value): self[0] = value # Y and Z likewise. 
+2
source

Source: https://habr.com/ru/post/1247468/


All Articles