前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >将类实例合并为其他实例

将类实例合并为其他实例

原创
作者头像
华科云商小徐
发布2025-02-13 09:40:50
发布2025-02-13 09:40:50
7900
代码可运行
举报
文章被收录于专栏:小徐学爬虫小徐学爬虫
运行总次数:0
代码可运行

如果你有多个类的实例,并且希望将它们合并成一个新的实例(即将这些实例的数据或者状态合并到一个新的对象中),你可以根据具体的需求设计合并的逻辑。下面是一个简单的例子,展示如何将多个类实例合并到一个新的实例中。

假设我们有一个类 Person,并且有多个 Person 实例,我们希望将这些实例的属性合并到一个新的实例中。我们可以通过自定义合并方法来实现。

1、问题背景

我在设计一个“拼图”工具,用于管理不同水管类型管件的组合,以获得不同的功能。

我有不同类型的单管件,每种管件都有不同的功能(冷却器、加热器、净化器等)。 这些不同接口尺寸的管件可以相互连接(1/4英寸、1/6英寸……)。

我希望这些管件可以存储在数据库中,并可以组合成一个新的管件组合(随机或有目的地),但仍然可以被认为是一个功能性管件。 以下是我最初的想法:

代码语言:javascript
代码运行次数:0
复制
class MetaInfo():
    def __init__(self, name, intype,outtype,shape,serialno):
        this.name = name
        this.intype = intype
        this.outtype = outtype
        this.shape = shape
        this.sn = serialno
​
def parts():
    def __init__(self, meta):
        this.meta = meta
​
    def linkwith(self, part):
        if part.meta.shape == this.meta.shape: 
        # make it simple, logical here is just same shape can be connected each other 
            return ???         # a new parts combination 
        else:
            raise Error 
​
m1 = MetaInfo("cooler", "hotwater", "coldwater", "1/4 inch round", "SN:11111" )
m2 = MetaInfo("heater", "coldwater", "hotwater", "1/4 inch round", "SN:22222" )
m3 = MetaInfo("purifier", "coldwater", "hotwater", "1/6 inch round", "SN:33333" )
​
a = parts(m1)
b = parts(m2)
c = parts(m3)

2、解决方案

代码语言:javascript
代码运行次数:0
复制
from copy import copy
import csv
​
class Part_Base(object):
    pass
​
class MultiPart_Base(list):
    pass
​
class part_meta(type):
    part_names = {}
    parts      = []
    def __init__(cls, cls_name, cls_bases, cls_dict):
        super(part_meta, cls).__init__(cls_name, cls_bases, cls_dict)
        if(not Part_Base in cls_bases):
            part_meta.part_names[cls_name] = cls
​
    def __call__(self, *args, **kwargs):
        name = kwargs.get("name", "")
        if(part_meta.part_names.has_key(name) and not (self is part_meta.part_names[name])):
            obj = part_meta.part_names[name].__call__(*args, **kwargs)
        else:
            obj = None
            if(not part_meta.part_names.has_key(self.__name__)):
                new_class = part_meta(name, (Generic_Part,), {})
                globals()[name] = new_class
                obj = new_class(*args, **kwargs)
            else:
                obj = super(part_meta, self).__call__(*args, **kwargs)
        if not obj in part_meta.parts:
            part_meta.parts.append(obj)
        return obj
​
    @classmethod
    def save(cls):
        all_fields = list(reduce(lambda x, y: x | set(y.fields), cls.parts, set([])))
        with open("parts.csv", "w") as file_h:
            writer = csv.DictWriter\
            (
                file_h,
                all_fields,
                restval        = "",
                extrasaction   = "ignore",
                dialect        = "excel",
                lineterminator = "\n",
​
            )
            writer.writeheader()
            for part in cls.parts:
                writer.writerow({field : getattr(part, field) for field in part.fields})
​
    @classmethod
    def load(cls):
        with open("parts.csv", "r") as file_h:
            reader = csv.DictReader(file_h)
            for row in reader:
                Part(**row)
​
class Part(Part_Base):
    __metaclass__ = part_meta
    fields        = []
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)
        self.fields += kwargs.keys()
​
    def __repr__(self):
        return "<%s>" % self.description
​
    @property
    def description(self):           
        return "%s: %s %s %s %s" % (self.name, self.intype, self.outtype, self.shape, self.serialno)
​
    def linkwith(self, *parts):
        return Generic_MultiPart(self, *parts)
​
class Generic_Part(Part):
    def __init__(self, **kwargs):
        kwargs["name"] = self.__class__.__name__
        super(Generic_Part, self).__init__(**kwargs)
​
class Generic_MultiPart(MultiPart_Base):
    def __init__(self, *parts):
        super(Generic_MultiPart, self).__init__()
        if len(parts) >= 2:
            self.shape = parts[0].shape
            self.linkwith(*parts)
        else:
            raise ValueError("Not enough parts")
​
    def __repr__(self):
        return "<MultiPart: %s>" % super(Generic_MultiPart, self).__repr__()
​
    def linkwith(self, *parts):
        for part in parts:
            if part.shape == self.shape:
                if isinstance(part, Part):
                    self.append(part)
                elif isinstance(part, MultiPart_Base):
                    self.extend(part)
            else:
                raise ValueError("Incompatible parts")
        return self
​
class cooler(Generic_Part):
    intype  = "hotwater"
    outtype = "coldwater"
    fields  = ["intype", "outtype"]
​
class heater(Generic_Part):
    intype  = "coldwater"
    outtype = "hotwater"
    fields  = ["intype", "outtype"]
​
def make_some_parts():
    some_parts = \
    [
        # This is actually a cooler object
        # The metaclass uses the cooler class from above
        # to create the object
        Part
        (
            name     = "cooler",
            shape    = "1/4 inch round",
            serialno = "SN:11111"
        ),
        # Using the heater class directly
        heater
        (
            shape    = "1/4 inch round",
            serialno = "SN:22222"
        ),
        Part
        (
            name     = "purifier",
            intype   = "coldwater",
            outtype  = "hotwater",
            shape    = "1/6 inch round",
            serialno = "SN:33333"
        ),
        Part
        (
            name     = "carbon_filter",
            intype   = "coldwater",
            outtype  = "coldwater",
            shape    = "1/4 inch round",
            serialno = "SN:33333"
        )
    ]
​
    useless_part = some_parts[0].linkwith(some_parts[1])
    print useless_part
    filter_part  = copy(useless_part).linkwith(some_parts[3])
    print filter_part
​
    part_meta.save()
​
def load_some_parts():
    part_meta.load()
    print part_meta.parts
​
You can manually edit parts.csv (in Excel or other) and it will make the parts described.
The save/restore functionality hasn't been extended to MultiParts; you can do that.

总结:

  1. 合并属性:可以通过类的静态方法来将多个实例的属性合并到一个新的实例。
  2. 自定义合并逻辑:根据需求,可以设计复杂的合并规则,比如对数字属性取平均,或者对列表进行合并和去重等。
  3. 灵活性:这种方式可以灵活地应用于不同类型的类,并根据类的具体属性定义合并策略。

这种方法适用于需要将多个实例合并为一个新实例的场景,尤其是当你想要保持原始数据的完整性并创建一个新的综合实例时。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档