Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将实例作为可选参数传递给另一个类_Python_Oop - Fatal编程技术网

Python 将实例作为可选参数传递给另一个类

Python 将实例作为可选参数传递给另一个类,python,oop,Python,Oop,我最近一直在进行OOP探索 我有两个类:一个用于事件,另一个用于计算该事件的一些属性集 class Event(object): def __init__(self,name,info): self.name = name self.category = info.category self.classification = info.classification @property def attributes(self

我最近一直在进行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'}
但我希望可以选择提供任何数量/组合的未来
class2
class3
等的
Event()
实例;因此,我需要
Event()
init()
方法优雅地处理它们,以便
e.attributes
将返回所有适当的属性。给
Event.\uuuuu init\uuuuu
a*参数解包似乎并没有绕过它需要知道需要分配给自己的属性名称的需要。最终,我想做的是能够创建这个事件,然后根据需要使用这个范例创建/更新它的不同属性集。有可能吗?

我想,有一个python对象,在您的示例中,您需要它来使
事件
完全忽略
信息的结构。如果一个设计只有通过黑客才能实现,那么它可能不是最健壮的一个——即使它看起来很糟糕


下面是一个事件类的示例,它不知道传入的
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'
现在,你们可以将任何一门课传递到事件中,但我不确定,这是否真的是你们的问题:

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'}

你说‘我有两个类:一个用于事件,另一个用于计算该事件的某些属性集。’你有这样做的充分理由吗?如果您有一个事件类,为什么不将这些计算出的属性作为事件的属性?

实现这一点的另一种方法不是在不知道类2、类3等的全部内容的情况下转储它们。您可以要求期望该类以某种方式发布其“public”属性,例如使用“get_attributes”方法。从编码便利性的角度来看,如果class2、class3等继承自一个共同的祖先,那么工作就少了,但是“duck access”它们完全可以:

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想法的“选择加入”替代方案-这可能是一个更安全的赌注,除非您确定您的帐户是唯一一个在事件>信息关系两端创建代码的帐户。一个很好的技巧是提供一个decorator,用get_attributes方法来调整现有的类

撇开意图的清晰性不谈,这也是一种小小的保护,可以防止遇到一个在其中一个字段中有1000行文本的古怪类:)


编辑以回应@mike的观察:如果get_属性刚刚从info对象返回了一个字典,那么这将更干净,这将是一种更纯粹的解耦,没有反射负担。我将代码保持原样,否则讨论就没有意义了,但正确的方法是在子级上调用“get_attributes”(如果存在),如果没有,则返回默认值。我的坏:)

首先,为什么要抄写((k,v)代表自我中的k,v.\uuuu dict\uuuu.items())
只是为了抄写?第二,你为什么要在口述的基础上伪造口述?也许你需要。我正试着理解你的问题,但不太清楚。我怀疑如果你解释得更好的话,你很有可能会自己想出答案?我的想法有点过头了,所以我很可能对xy问题感到内疚,但我会尽量详细说明。Miku几乎拥有我想要的东西,除了我在一个附加过程之后:我想在他提到的两个示例调用之后更新
e.attributes
,这样它的值将是
{'I_am_完全不同':'是的,的确如此','name':'myevent','category':'category value','classification':'classification value','number':42}
。为了回答Mike的问题,这是因为当我第一次创建
e
时,我可能没有所有类所需的所有信息,但我不想零碎地更新属性。@verbsintransit这个设计对我来说仍然没有任何意义。如果类1和类2只是作为dicts,为什么不使用dicts呢?如果类1和类2不是简单的dict,因为它们有getter和setter,那么为什么需要Event类呢?它唯一的功能似乎是报告另一个类的所有公共属性。如果所有这些类之间都有共同的逻辑,那么它们无论如何都是子类,您应该从事件继承。解耦的关键是限制一个类对其使用的类的了解程度。正如Miku所说,在类的内部进行搜索从来都不是完全安全的——如果对某个信息类调用属性访问器会触发数据库查询或HTTP get呢?要求子类对某些“EventInfo”类进行子类化是一种可行的方法;寻找一种特殊的方法是另一种方法。在其他语言中,您将定义一个接口——在Python中,标准方法是按名称期望方法——以“文件类对象”为例……类2中的名称和数据是如何私有的?另外,您不需要将课程传递给Event吗?撇开这些问题不谈,这种设计非常粗糙-必须有一个更好的解决方案来实现OP的根本目的。隐私纯粹是概念性的-只是表明它们不会发布到活动系统中。我的观点是OP想要的是非常普遍的,它可能会导致比它解决的问题更多的问题。如果实现完美解耦的唯一方法是对未知类的内部进行详细的反射,那么它并不是非常有用。在Python中,表示隐私的标准方法是一个前导的双下划线,例如self.\u在您的示例中是self.\u Name。正如我所说,“隐私”纯粹是为了事件类的目的。否则,我们仍在反思/检查,以确定该做什么;请看我在原始问题中的评论。@verbsintransit在那里回答了-我怀疑是y