首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我如何在Python中创建一家米辛工厂?

我如何在Python中创建一家米辛工厂?
EN

Stack Overflow用户
提问于 2012-01-31 21:16:12
回答 2查看 2.3K关注 0票数 4

我有许多类被其他类包装以添加新功能。

不幸的是,包装器类没有为它们包装的类实现传递函数,因此包装器不能与原始类互换使用。

我想动态地创建包含包装器和原始类的功能的类。

我的想法是创建一个混合类,并使用一个工厂将其应用到现有的类中,动态地创建一个新的双重用途类。这应该允许我一次性编写混合功能,并将混合类用于通过一个对象提供原始功能或来自混合的增强功能。

这就是我想要的东西:

代码语言:javascript
复制
class A:
    def __init__(self):
        self.name = 'A'

    def doA(self):
        print "A:", self.name


class B(A):
    def __init__(self):
        self.name = 'B'

    def doB(self):
        print "B:", self.name


class C(A):
    def __init__(self):
        self.name = 'C'

    def doC(self):
        print "C:", self.name


class D:
    def doD(self):
        print "D:", self.name


class BD(B,D):
    pass


def MixinFactory(name, base_class, mixin):
    print "Creating %s" % name
    return class(base_class, mixin)     # SyntaxError: invalid syntax

a, b, c, d, bd = A(), B(), C(), D(), BD()

bd2 = MixinFactory('BD2', B, D)()
cd = MixinFactory('CD', C, D)()

a.doA()     # A: A

b.doA()     # A: B
b.doB()     # B: B

c.doA()     # A: C
c.doC()     # C: C

bd.doA()    # A: B
bd.doB()    # B: B
bd.doD()    # D: B

bd2.doA()   # A: B
bd2.doB()   # B: B
bd2.doD()   # D: B

cd.doA()    # A: C
cd.doC()    # C: C
cd.doD()    # D: C

问题是,很明显,不能只从函数返回一个类。不过,忽略语法错误,上面的代码确实显示了我正在努力实现的目标。

我玩过type()的三个参数变体,但无法让它起作用,所以我不确定这是否是正确的方法。

我假设在Python中可以创建这种类型的混合工厂,那么我需要了解什么才能实现它呢?

正如Niklas R所评论的,this answer to the provides Python dynamic inheritance: How to choose base class upon instance creation?为我的查询提供了解决方案,但Ben在这里的回答更好地解释了为什么。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-31 21:24:16

实际上,您可以从函数返回一个类。语法错误是使用类关键字,就好像它是可以调用的函数一样。

请记住,类块的所有内容都是创建一个新类,然后将您选择的名称绑定到它(在当前范围中)。所以,只需在函数中放置一个类块,然后返回类!

代码语言:javascript
复制
def mixinFactory(name, base, mixin):
    class _tmp(base, mixin):
        pass
    _tmp.__name__ = name
    return _tmp

正如ejucovy所指出的,您也可以直接调用type

代码语言:javascript
复制
def mixinFactory(name, base, mixin):
    return type(name, (base, mixin), {})

这是因为(通常)类块实际上所做的事情;它将类块中定义的所有名称收集到字典中,然后将类的名称、基类的元组和字典传递给type来构造新的类。

然而,type不过是默认的元类。类和其他所有东西一样都是对象,是类的实例。大多数类都是type的实例,但是如果涉及到另一个元类,您应该调用它而不是type,就像您不会调用object来创建类的新实例一样。

mixin (大概)没有定义元类,所以它应该与type的子类兼容。因此,您只需使用base类的任何内容:

代码语言:javascript
复制
def mixinFactory(name, base, mixin):
    return base.__class__(name, (base, mixin), {})

然而,S.Lott的评论确实是这个问题最好的“答案”,除非您的混合工厂所做的事情比创建一个新类更复杂。这比提出的任何动态类创建变体都要清晰得多,而且类型更少:

代码语言:javascript
复制
class NewClass(base, mixin):
    pass
票数 7
EN

Stack Overflow用户

发布于 2012-01-31 21:27:29

您可以在任何地方都有类声明,类声明可以引用变量进行子类化。至于类名,它只是类对象上的.__name__属性。所以:

代码语言:javascript
复制
def MixinFactory(name, base_class, mixin):
  print "Creating %s" % name
  class kls(base_class, mixin):
    pass
  kls.__name__ = name
  return kls

应该这么做。

对于一行,三参数type函数也应该工作:

代码语言:javascript
复制
def MixinFactory(name, base_class, mixin):
  return type(name, (base_class, mixin), {})
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9087072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档