[英]Passing instances as optional arguments to another class
我最近一直在進行OOP探索。
我有兩個類:一個用於事件,另一個用於計算該事件的某些屬性。
class Event(object):
def __init__(self,name,info):
self.name = name
self.category = info.category
self.classification = info.classification
@property
def attributes(self):
return dict((k,v) for k,v in self.__dict__.items())
class class1(object):
def __init__(self,some_number):
self.number = some_number
@property
def category(self):
#stuff
return category
@property
def classification(self):
#stuff
return classification
現在我可以做類似的事情
e = Event('myevent', class1(42))
e.attributes
{'category': 1,
'classification': None,
'name': 'myevent'}
但我想選擇給Event()
實例提供未來class2
, class3
等的任何數量/組合的實例; 因此,我希望Event()
的init()
方法來適當地處理它們,以便e.attributes
返回所有適當的屬性。 給Event.__init__
一個* param來解壓縮似乎並沒有繞過它知道它需要分配給自己的屬性名稱的需要。 最終,我想做的就是能夠創建此事件,然后使用此范例在以后根據需要創建/更新其不同的屬性集。 可能嗎?
我猜想,沒有一種完全干凈的方法來僅獲取 python對象的用戶定義屬性 ,這是您在示例中需要使Event
完全不了解info
結構的方式。 而且,即使只有駭客才能實現的設計,也可能不是最可靠的設計,即使它看起來像OOD。
在Event類的示例下面,它忽略傳入的info
對象的實際屬性:
class Event(object):
# instead of accepting attributes, just deal with a single object 'info'
def __init__(self, name, info):
self.name = name
self.info = info
@property
def attributes(self):
# attributes will consist of
# A) Event's name - fixed
# B) info objects hopefully 'public' attributes, which we need
# to lookup at runtime
attrs = {'name': self.name}
for attr in [name for name in dir(self.info)
if not name.startswith('_')]:
attrs[attr] = getattr(self.info, attr)
return attrs
Class1
和Class2
並沒有太多共享:
class Class1(object):
def __init__(self, some_number):
# some initial attribute
self.number = some_number
@property
def category(self):
# stuff
return 'category value'
@property
def classification(self):
# stuff
return 'classification value'
class Class2(object):
@property
def i_am_totally_different(self):
return 'yes, indeed'
現在您可以將任何類傳遞給Event,但是不確定那是否真的是您的問題:
e = Event('myevent', Class1(42))
print(e.attributes)
# {'category': 'category value', 'name': 'myevent',
# 'classification': 'classification value', 'number': 42}
e = Event('myevent', Class2())
print(e.attributes)
# {'i_am_totally_different': 'yes, indeed', 'name': 'myevent'}
您說:“我有兩類:一類用於事件,一類用於計算該事件的某些屬性。” 您有這樣做的充分理由嗎? 如果您有事件類,為什么不將那些計算出的屬性作為事件的屬性呢?
替代方法不是在不知道它們是什么的情況下轉儲class2,class3等的全部內容。 您可以要求該類以某種方式發布其“公共”屬性,例如使用“ get_attributes”方法。 從編碼便利性的角度來看,如果class2,class3等是從一個共同的祖先繼承而來的,則工作量較小,但是“直接訪問”它們是完全可以的:
class Event(object):
def __init__(self, name, info):
self.Name = name
self.Info = info
@property
def attributes():
result = { k: getattr(info, k) for k in info.get_attributes() }
return result
class Class1(object):
def __init__ (name, classification, other)
self.Name = name
self.Other = other
self.Classification = classification
def get_attributes(self):
return ("Name", "Classification" ) # in this case not "Other"...
class Class2(object):
def __init__(self, privateName, orivateData, publicName):
self.Name = privateName
self.Data = privateData
self.Public = publicName
def get_attributes(self):
return ("Public",)
這是@miku想法的“選擇加入”替代方案-除非您確定自己是唯一在事件>信息關系兩端創建代碼的人,否則這可能是一個更安全的選擇。 一個不錯的技巧是提供一個裝飾器,以使用get_attributes方法來適應現有的類。
除了意圖明確之外,這還可以防止進入其中一個字段中有成千上萬行文字的怪異類:)
編輯響應@mike的觀察:如果get_attributes剛剛從info對象返回了一個字典,這將更干凈,這將是一個更加純凈的去耦,而沒有反射負擔。 我將代碼保留原樣,否則討論將毫無意義,但正確的方法是在子級上調用“ get_attributes”(如果存在),如果不存在則返回默認值。 我的錯 :)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.