应用场景
某C++软件有一个运行python脚本的小工具,该工具通过pybind11实现了某些复杂C++类和预定义Python类的绑定与转换关系;
预期:用户在编写python脚本并在软件内使用该工具调试脚本时,对于某个预定义的Python对象,如果给某个类成员变量赋值类型错误,希望直接python侧(即脚本中)报错并提示用户。
代码
#C++软件预定义的python类
class PyLine3D:
"""
Represents a line in 3D space defined by a point on the line and a direction vector.
Attributes:
point (PyVector3D): A point on the line.
direction (PyVector3D): The direction vector of the line. It is not required to be a unit vector.
However, a unit vector is recommended for normalization.
"""
def __init__(self, point=PyVector3D(), direction=PyVector3D(0.0, 0.0, 1.0)):
if not isinstance(point, PyVector3D):
raise TypeError(f"[{self.__class__.__name__}]: point must be an instance of PyVector3D")
if not isinstance(direction, PyVector3D):
raise TypeError(f"[{self.__class__.__name__}]: direction must be an instance of PyVector3D")
self.__point = point
self.__direction = direction
@property
def point(self):
return self._PyLine3D__point
@point.setter
def point(self, value):
if isinstance(value, PyVector3D):
self._PyLine3D__point = value
else:
raise TypeError(f"[{self.__class__.__name__}]: point must be an instance of PyVector3D")
@property
def direction(self):
return self._PyLine3D__direction
@direction.setter
def direction(self, value):
if isinstance(value, PyVector3D):
self._PyLine3D__direction = value
else:
raise TypeError(f"[{self.__class__.__name__}]: direction must be an instance of PyVector3D")
def __repr__(self):
return f"PyLine3D(point={self.point}, direction={self.direction})"
# 用户侧使用
def create_shape3dList():
line1 = PyLine3D(PyVector3D(1.0, 1.0, 1.0), PyVector3D(1.0, 1.0, 0.0))
line2 = PyLine3D()
line2.point = PyVector3D(1.1, 1.2, 1.3) # can be PyVector3D or PyPoint3D
line2.direction.x = 0.0 # must be a float number, instead of int
line2.direction.y = 1.0
line2.direction.z = 1.0
return [line1, line2]
细节注意点
- 构造函数使用__修饰成员变量后,自动触发名称重整(Name Mangling),重整为:_{class_name}__{var_name}
- @property 装饰器用于将类的方法转换为属性。它允许你像访问属性一样访问一个方法的返回值,而不需要显式地调用这个方法;此时该属性默认是只读的
- @{var_name}.setter 是 @property 装饰器的一个扩展,用于定义属性的setter方法。它允许你为一个属性定义自定义的赋值逻辑,即当用户试图设置该属性的新值时,可以通过 @setter 进行控制和验证。