簡體   English   中英

將實例作為可選參數傳遞給另一個類

[英]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()實例提供未來class2class3等的任何數量/組合的實例; 因此,我希望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

Class1Class2並沒有太多共享:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM