Python(2.7):动态添加类方法

Python(2.7):动态添加类方法,python,Python,我有一些类,我希望能够将它们的方法添加到上的其他类中。我最初的解决方案是使用mixin,但这可能会有点难看: class Schedule(Enumerator, Humanizer, Inferer, ...): ... 所以我想,嘿,也许我可以使用类装饰器来达到同样的效果 @enumerator @humanizer @inferer class Schedule(object): ... 下面是装饰器函数的示例: import inspect def inferer(

我有一些类,我希望能够将它们的方法添加到上的其他类中。我最初的解决方案是使用mixin,但这可能会有点难看:

class Schedule(Enumerator, Humanizer, Inferer, ...):
    ...
所以我想,嘿,也许我可以使用类装饰器来达到同样的效果

@enumerator
@humanizer
@inferer
class Schedule(object):
    ...
下面是装饰器函数的示例:

import inspect

def inferer(original_class):
    from myproj.lib.inferer import Inferer
    methods = inspect.getmembers(Inferer, predicate=inspect.ismethod)
    for method in methods:
        setattr(original_class, method[0], types.MethodTypes(method[1], original_class))
    return original_class
…它似乎将方法和类方法适当地添加到修饰类中。然而,当我在装饰类上调用这些添加的方法(或classmethods)时,我会得到一些错误

对于方法:

>>> Schedule().humanize()
TypeError: unbound method humanize() must be called with Humanizer instance as first argument (got type instance instead)
…这似乎表明这些是作为类方法添加的

对于类方法:

>>> schedule = Schedule.infer(foo)
TypeError: infer() takes exactly 2 arguments (3 given)
请注意推断的定义:

class Inferer(object):
    @classmethod
    def infer(cls, dates):
        ...
我在
expert
中添加了一些行,以显示调用
Schedule.infer()时它得到的参数:

cls:
日期:

所以,我的问题是:

decorator函数中出现了什么问题导致这些添加的方法和类方法行为异常?或者,更好地说,如何修改decorator函数以正确处理这些添加


如果我能就任何一点提供任何澄清,请告诉我。

假设这是一个好主意。这是你可能实现它的一种方法。不过,我不能说我会提出建议

def horrible_class_decorator_factory(mixin):
    def decorator(cls):
        d = cls.__dict__.copy()
        bases = tuple([b for b in cls.__bases__ if b != object] + [mixin])
        return type(cls.__name__, bases, d)
    return decorator
现在您可以执行以下操作:

class Inferer(object):
    @classmethod
    def foo(cls):
        return "bar" + cls.__name__

inferer = horrible_class_decorator_factory(Inferer)

@inferer
class X(object):
    pass

X.foo()
"barX"

在这一点上,我和评论家们是一致的。仅仅因为你能做某事并不意味着你应该做。

所以。。。使用decorator的唯一原因是因为传统语法看起来很难看?这听起来像是一个巨大的工作量和额外的代码脆弱性只是为了美观。我不知道为什么你认为使用这样的装饰器会比使用mixin更丑陋(问题)。也就是说,您可能需要利用一个元类来完成您正试图完成的任务。几年前,我回忆起建立了一个系统,该系统通过函数集合动态创建类,我为此使用了元类(抱歉,现在不记得所有细节)。我同意:混音看起来更简单、更清晰,而且它们确实可以工作。为什么要这么麻烦呢?有没有什么特别的原因需要将classmethods附加到计划中?因为它们是类方法,所以你也可以直接调用它们,例如,推断类。有什么原因吗?我从评论者和你那里听到的是,这是一个可怕的想法,也是脆弱的(顺便说一句,谢谢你的函数名)。尤其有用。Python应该易于阅读和理解,一旦你开始胡乱处理最基本的语法内容,你就开始引入代码脆性和缺乏清晰度的可能性。因为你的美感,做事很有诱惑力。请记住,设计这种语言的人花了很多心思。他们给了你很多内省和定制的力量,但这已经足够让你上吊了。想想一个很好的例子,为什么这是不好的。假设您有一些这样的mixin,也许出于某种原因,您让它们从一个公共基类继承。我没有对基类做任何类型的检查。突然,我引入了方法解析顺序(MRO)问题。如果您希望看到一个有效实现这一点的示例,请查看Django模型基类。它很快变得非常复杂。我很感谢你举个例子说明它为什么不好。在没有任何解释的情况下被告知一种技术是可怕的,这是非常令人沮丧的。我想我已经在整个项目上绕了一圈,最初尝试动态地混合,基于这个“讨论”,我将重构。我会接受你的回答,因为它确实解决了我提出的问题。令人信服的理由非常重要。否则,你会觉得这是武断的,你不会带着任何新的理解离开你所面临的问题。
class Inferer(object):
    @classmethod
    def foo(cls):
        return "bar" + cls.__name__

inferer = horrible_class_decorator_factory(Inferer)

@inferer
class X(object):
    pass

X.foo()
"barX"