如果你有多個(gè)類的實(shí)例输枯,并且希望將它們合并成一個(gè)新的實(shí)例(即將這些實(shí)例的數(shù)據(jù)或者狀態(tài)合并到一個(gè)新的對(duì)象中),你可以根據(jù)具體的需求設(shè)計(jì)合并的邏輯占贫。下面是一個(gè)簡單的例子桃熄,展示如何將多個(gè)類實(shí)例合并到一個(gè)新的實(shí)例中。
假設(shè)我們有一個(gè)類 Person靶剑,并且有多個(gè) Person 實(shí)例蜻拨,我們希望將這些實(shí)例的屬性合并到一個(gè)新的實(shí)例中。我們可以通過自定義合并方法來實(shí)現(xiàn)桩引。
1、問題背景
我在設(shè)計(jì)一個(gè)“拼圖”工具收夸,用于管理不同水管類型管件的組合坑匠,以獲得不同的功能。
我有不同類型的單管件卧惜,每種管件都有不同的功能(冷卻器厘灼、加熱器、凈化器等)咽瓷。這些不同接口尺寸的管件可以相互連接(1/4英寸设凹、1/6英寸……)。
我希望這些管件可以存儲(chǔ)在數(shù)據(jù)庫中茅姜,并可以組合成一個(gè)新的管件組合(隨機(jī)或有目的地)闪朱,但仍然可以被認(rèn)為是一個(gè)功能性管件。以下是我最初的想法:
classMetaInfo():
def__init__(self,name,intype,outtype,shape,serialno):
this.name=name
this.intype=intype
this.outtype=outtype
this.shape=shape
this.sn=serialno
defparts():
def__init__(self,meta):
this.meta=meta
deflinkwith(self,part):
ifpart.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:
raiseError
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钻洒、解決方案
fromcopyimportcopy
importcsv
classPart_Base(object):
pass
classMultiPart_Base(list):
pass
classpart_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(notPart_Baseincls_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)andnot(selfispart_meta.part_names[name])):
obj=part_meta.part_names[name].__call__(*args,**kwargs)
else:
obj=None
if(notpart_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)
ifnotobjinpart_meta.parts:
part_meta.parts.append(obj)
returnobj
@classmethod
defsave(cls):
all_fields=list(reduce(lambdax,y:x|set(y.fields),cls.parts,set([])))
withopen("parts.csv","w")asfile_h:
writer=csv.DictWriter\
? ? ? ? ?? (
file_h,
all_fields,
restval="",
extrasaction="ignore",
dialect="excel",
lineterminator="\n",
? ? ? ? ?? )
writer.writeheader()
forpartincls.parts:
writer.writerow({field:getattr(part,field)forfieldinpart.fields})
@classmethod
defload(cls):
withopen("parts.csv","r")asfile_h:
reader=csv.DictReader(file_h)
forrowinreader:
Part(**row)
classPart(Part_Base):
__metaclass__=part_meta
fields=[]
def__init__(self,**kwargs):
forname,valueinkwargs.items():
setattr(self,name,value)
self.fields+=kwargs.keys()
def__repr__(self):
return"<%s>"%self.description
@property
defdescription(self):
return"%s: %s %s %s %s"%(self.name,self.intype,self.outtype,self.shape,self.serialno)
deflinkwith(self,*parts):
returnGeneric_MultiPart(self,*parts)
classGeneric_Part(Part):
def__init__(self,**kwargs):
kwargs["name"]=self.__class__.__name__
super(Generic_Part,self).__init__(**kwargs)
classGeneric_MultiPart(MultiPart_Base):
def__init__(self,*parts):
super(Generic_MultiPart,self).__init__()
iflen(parts)>=2:
self.shape=parts[0].shape
self.linkwith(*parts)
else:
raiseValueError("Not enough parts")
def__repr__(self):
return"<MultiPart: %s>"%super(Generic_MultiPart,self).__repr__()
deflinkwith(self,*parts):
forpartinparts:
ifpart.shape==self.shape:
ifisinstance(part,Part):
self.append(part)
elifisinstance(part,MultiPart_Base):
self.extend(part)
else:
raiseValueError("Incompatible parts")
returnself
classcooler(Generic_Part):
intype="hotwater"
outtype="coldwater"
fields=["intype","outtype"]
classheater(Generic_Part):
intype="coldwater"
outtype="hotwater"
fields=["intype","outtype"]
defmake_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])
printuseless_part
filter_part=copy(useless_part).linkwith(some_parts[3])
printfilter_part
part_meta.save()
defload_some_parts():
part_meta.load()
printpart_meta.parts
Youcanmanuallyeditparts.csv(inExcelorother)anditwillmakethepartsdescribed.
Thesave/restorefunctionalityhasn't been extended to MultiParts; you can do that.
總結(jié):
合并屬性:可以通過類的靜態(tài)方法來將多個(gè)實(shí)例的屬性合并到一個(gè)新的實(shí)例奋姿。
自定義合并邏輯:根據(jù)需求,可以設(shè)計(jì)復(fù)雜的合并規(guī)則素标,比如對(duì)數(shù)字屬性取平均称诗,或者對(duì)列表進(jìn)行合并和去重等。
靈活性:這種方式可以靈活地應(yīng)用于不同類型的類头遭,并根據(jù)類的具體屬性定義合并策略寓免。
這種方法適用于需要將多個(gè)實(shí)例合并為一個(gè)新實(shí)例的場(chǎng)景,尤其是當(dāng)你想要保持原始數(shù)據(jù)的完整性并創(chuàng)建一個(gè)新的綜合實(shí)例時(shí)计维。