python (2.7) : dynamically adding classmethods

标签 python

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

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

...这似乎将方法和类方法适本地添加到装饰类中。但是,当我在装饰类上调用这些添加的方法(或类方法)之一时,出现了一些错误。

对于方法:

>>> 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)

注意infer的定义:

class Inferer(object):
    @classmethod
    def infer(cls, dates):
        ...

我在 infer 中添加了一些行,以显示它在调用 Schedule.infer() 时获得的参数:

cls: <class 'myproj.lib.inferer.Inferer'>
dates: <class 'myproj.Schedule'>

那么,我的问题是:

装饰器函数中出了什么问题导致这些添加的方法和类方法表现异常?或者,更好地说,我如何修 retrofit 饰器函数以正确处理这些添加?

如果我可以就任何一点提供任何说明,请告诉我。

最佳答案

假设这是个好主意。这是您可以实现它的一种方式。不过,我不能说我会建议它。

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"

我和评论者一起评论这个。仅仅因为您可以做某事并不意味着您应该做。

关于 python (2.7) : dynamically adding classmethods,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13336768/

相关文章:

python - 如何通过类python中的特定子字符串查找带有类字符串的span

python - PEP0484 类型提示 : Annotating argument of given class, 不是实例

python - C++ 中的长数字

python - 如何在列表中拆分字符串以在 Python 中创建键值对

python - 创建 token : cannot concatenate 'str' and 'NoneType' objects 很危险

python - 使用索引和名称列重命名索引

python - 如何强制先迁移 'django.contrib.sites'?

python - 我想使用 xlwings 将变量传递到我的 VBA 中,但似乎不起作用

python - 在 python 的unittest测试套件中强制执行测试顺序

python - 如果您有时间和意愿创建一种编程语言,它会具有什么特征?