使用外部类实例作为内部类中的self?

时间:2018-09-16 00:58:40

标签: python library-design

我正在为GMAIL API写一个包装。在此包装器中,我试图将子属性包含在“主类”中,以便更紧密地遵循以下内容:

picture

以前,我使用的方法如下:

class Foo:
    def __init__(self, ...):
        # add some attributes

    def get_method(self, ...):
        return some_stuff

这使我可以做foo.get_method(...)。要遵循GMAIL API,我尝试这样做:

class Foo:
     def __init__(self, ...):
         # add some attributes

     @property
     def method(self):
         class _Method:
             @staticmethod
             def get(self, ...):
                 return some_stuff
         return _Method()

这允许我做foo.method.get(...)。上面有一些问题,它每次都会重新定义该类,因此我必须在每个方法之上添加@staticmethod作为它的一部分。我确实意识到我可以在外部类级别创建该类,并为每个隐藏方法设置一个变量,然后.method返回或创建该变量,但这似乎是过多的解决方法。

tldr :是否可以使作为self传递给内部类的实例成为外部类的实例(我不希望通过传递外部类到每个内部类)。

3 个答案:

答案 0 :(得分:1)

用户应具有消息实例,该消息实例允许方法get。代码的获取是:

class Messages:
      ...
      def get()
            ...


class Users:
      ...
      messages = Messages(...)

允许

users =  Users()
users.messages.get()

此API中的坏事是复数名称,这对类来说是一个坏兆头。如果从头开始,您宁愿拥有User和Message类,这更有意义。

如果您仔细查看所提供的API中的GET / POST调用,您会注意到这些URL类似于UserId/settings,这是实现User类而非User的另一个提示。

答案 1 :(得分:1)

与其在类之间共享self参数,不如将所需的内容传递给实例化的类的构造函数,可能更好。

class Messages:
    def __init__(self, name):
        self.name = name

    def method(self, other_arg):
        return self.name + other_arg

class Test:
    name = "hi"

    def __init__(self):
        self.messages = Messages(name=self.name)

如果需要将大量信息传递给构造函数,并且开始变得笨拙,则可以执行以下操作,例如将共享代码拆分为第三类,然后将其作为单个对象传递给Test和Messages类。

在Python中,您可以使用元类和魔术方法执行各种巧妙的操作,但是在99%的情况下,只需将事物重构为不同的类和函数,便可以使您的代码更具可读性和可维护性。

答案 2 :(得分:0)

  方法中的

self引用外部类的self

也许这就是您想要的factory-method

尽管我将在下面提供的示例代码可能与已经提供的答案相似,并且上方指向另一个答案的链接可能会满足您的要求,因为它略有不同,我仍然会根据您的要求提供我的看法。该代码不言自明。

class User:
    def __init__(self, pk, name):
        self.pk = pk
        self.name = name
        self._messages = None

    def messages(self):
        if self.messages is None:
            self._messages = Messages(self.pk)
        return self._messages


class Messages:
    def __init__(self, usr):
        self.usr = usr

    def get(self):
        return self._grab_data()

    def _grab_data(self):
        # grab the data from DB
        if self.usr == 1:
            print('All messages of usr 1')
        elif self.usr == 2:
            print('All messages of usr 2')
        elif self.usr == 3:
            print('All messages of usr 3')



one = User(1, 'One')
two = User(2, 'Two')
three = User(3, 'Three')

one.messages().get()
two.messages().get()
three.messages().get()

对于标签,历史记录等,实用的messages方法是相同的。

编辑:即使您说了

,我也会再试一次,以了解您想要实现的目标
  

我尝试了许多事情来定义容器类之外的类[...]

。我不知道您是否尝试过继承,因为您的内部类me尽管在这里完全不表示任何内容,但看起来您仍然想以某种方式利用它的功能。您也说过

  方法中的

self引用外部类的self

对我来说,这听起来像您想最后继承。 那么要走的路是(使用继承的邻近点):

class me(object):
    def __init__(self):
        self.__other_arg = None # private and hidden variable
    # setter and getter methods
    def set_other_arg(self, new_other_arg):
        self.__other_arg = new_other_arg
    def get_other_arg(self): 
        return self.__other_arg

class Test(me):
    name = 'Class Test'
    @property
    def message(self):
        other_arg = self.get_other_arg()
        if other_arg is not None:
            return '{} {}'.format(self.name, other_arg)
        else:
            return self.name

t = Test()
t.set_other_arg('said Hello')
print(t.message)
# output >>> Class Test said Hello

我认为,这可能是一种比您的内在方法更好的选择,我认为您会决定。仅需注意一点,在python中查找getter和setter,如果您想坚持给出的继承思想,可能会对您有所帮助。