pythonapi设计模式问题

pythonapi设计模式问题,python,Python,我经常发现我的类实例是其他类实例的后代,以类似于树的方式。例如,假设我正在用Python制作一个CMS平台。我可能有一个领域,下面是一个博客,下面是一篇文章。每个构造函数都将其父级作为第一个参数,以便知道它属于什么。可能是这样的: class Realm(object): def __init__(self, username, password) class Blog(object): def __init__(self, realm, name) class Post(o

我经常发现我的类实例是其他类实例的后代,以类似于树的方式。例如,假设我正在用Python制作一个CMS平台。我可能有一个领域,下面是一个博客,下面是一篇文章。每个构造函数都将其父级作为第一个参数,以便知道它属于什么。可能是这样的:

class Realm(object):
    def __init__(self, username, password)

class Blog(object):
    def __init__(self, realm, name)

class Post(object);
    def __init__(self, blog, title, body)
class Realm(object):
    def __init__(self, username, password):
        ...
    def createBlog(self, name):
        return Blog(self, name)
我通常会在父类中添加一个create方法,这样链接会更加自动。我的领域类可能如下所示:

class Realm(object):
    def __init__(self, username, password)

class Blog(object):
    def __init__(self, realm, name)

class Post(object);
    def __init__(self, blog, title, body)
class Realm(object):
    def __init__(self, username, password):
        ...
    def createBlog(self, name):
        return Blog(self, name)
这允许API用户不必导入每个模块,只导入顶层模块。可能是这样的:

realm = Realm("admin", "FDS$#%")
blog = realm.createBlog("Kittens!")
post = blog.createPost("Cute kitten", "Some HTML blah blah")
问题是那些create方法是冗余的,我必须在两个地方对相同的参数进行pydoc

我想知道是否有一种模式(可能使用元类)将一个类实例链接到父类实例。我可以这样调用代码,让博客知道它的父域是什么:

realm = Realm("admin", "FDS$#%")
blog = realm.Blog("Kittens!")

您可以为具有
add()
方法的容器使用公共基类

class Container(object):
    def __init__(self, parent=None):
        self.children = []
        self.parent = parent
    def add(self, child)
        child.parent = self
        self.children.append(child)
        return child
并使派生类中的
parent
参数为可选

class Blog(Container):
    def __init__(self, name, realm=None):
        Container.__init__(realm)
        self.name = name
上面的代码现在可以读取了

realm = Realm("admin", "FDS$#%")
blog = realm.add(Blog("Kittens!"))
post = blog.add(Post("Cute kitten", "Some HTML blah blah"))
您将不再有任何
create…()
方法,因此无需两次记录任何内容

如果设置父项不仅仅涉及修改
parent
属性,那么可以使用属性或setter方法

编辑:正如您在下面的评论中指出的,孩子们应该在CONSTRUCTOR的末尾与父母联系在一起。可以修改上述方法以支持这一点:

class Container(object):
    def __init__(self, parent=None):
        self.children = []
        self.parent = None
    def add(self, cls, *args)
        child = cls(self, *args)
        self.children.append(child)
        return child

class Realm(Container):
    def __init__(self, username, password):
        ...

class Blog(Container):
    def __init__(self, realm, name):
        ...

class Post(Container):
    def __init__(self, blog, title, body):
        ...

realm = Realm("admin", "FDS$#%")
blog = realm.add(Blog, "Kittens!")
post = blog.add(Post, "Cute kitten", "Some HTML blah blah")

像这样的东西怎么样,只是子类化它。在我的领域构造函数中:

class Realm(object):
    def __init__(self, username, password):
        ...
        parent = self
        original_constructor = blog.Blog.__init__
        class ScopedBlog(blog.Blog):
            def __init__(self, *args):
                self.parent = parent
                original_constructor(self, *args)
        self.Blog = ScopedBlog

似乎有效。它可以用基类或元类来概括。

你的意思是实例是彼此的后代。有那么一会儿,我以为你在重新发明OOP。你是对的,我更新了这个问题。这是可行的,但我在想办法在构造函数运行结束时将它们结合起来。因此,如果没有父对象,博客甚至不能暂时存在(可能会引发类似“无法直接构造,请从父对象的上下文构造它”之类的异常)。您的add方法需要在此处返回子对象。当前add没有返回任何内容,因此行blog=realm.add(..)将导致blog==None@darkporter:编辑我的答案以反映这一点。嗯,我喜欢这样。它为您提供双向链接,以便您可以迭代您的孩子。让我来玩。答案被接受。在这种情况下,我将从构造函数参数中删除父对象。我要检查的只是一个通用的“家长”财产。