基于factory_boy构建带关联数据的SampleFactory实现方案
方案合理性分析
你提出的两种实现方案都可以满足需求,各自优缺点如下:
- 方案1(重写
_create方法):
逻辑集中,适合random_sample为唯一数据源、不需要自定义传入image/label的场景。但你当前的实现存在bug:直接读取cls._meta.parameters只会拿到类默认的参数值,用户调用工厂时传入的自定义参数(比如SampleFactory(shape=(128,128)))会被忽略,无法生效。同时该实现会完全忽略外部传入的image/label字段,灵活性很差,无法满足指定特定样本生成的测试需求。 - 方案2(使用
exclude参数):
是更合理的实现,完全兼容factory_boy的原生逻辑,支持外部传入自定义image/label/shape参数覆盖默认值,也不会影响子类继承,仅多了一个被排除的中间字段data,无实际副作用。
更优实现方案
如果需要复用你已经定义好的ImageFactory和LabelFactory的现有逻辑(比如后续你给两个工厂新增了字段、校验规则等),可以采用exclude+SelfAttribute+SubFactory的组合写法,既保证image和label的关联性,又符合factory_boy的使用习惯:
class SampleFactory(factory.Factory): class Meta: model = Sample # 排除中间变量,不传入Sample模型 exclude = ("sample_data",) class Params: shape = (32, 32) # 一次调用生成关联的图像和标签数组 sample_data = factory.LazyAttribute(lambda o: random_sample(o.shape)) # 复用现有工厂,传入预生成的数组,保留工厂原有逻辑 image = factory.SubFactory(ImageFactory, array=factory.SelfAttribute("..sample_data[0]")) label = factory.SubFactory(LabelFactory, array=factory.SelfAttribute("..sample_data[1]"))
该实现同时支持自定义参数覆盖,比如SampleFactory(shape=(128,128), label=custom_label)都可以正常生效。
内容的提问来源于stack exchange,提问作者Ramon
相关产品推荐
相关产品推荐

