django可分解装饰器static方法

时间:2019-01-26 11:15:34

标签: python django

以下是deconstruct类装饰器的源代码,我对类中使用staticmethod感到有些困惑,因为如果将代码klass.__new__ = staticmethod(__new__)更改为klass.__new__ = __new__,它仍然可以正常工作意料之中,谁能解释我为什么在这里使用staticmethod?目的或用例是什么?

from importlib import import_module

def deconstructible(*args, path=None):
    """
    Class decorator that allows the decorated class to be serialized
    by the migrations subsystem.
    The `path` kwarg specifies the import path.
    """
    def decorator(klass):
        def __new__(cls, *args, **kwargs):
            # We capture the arguments to make returning them trivial
            obj = super(klass, cls).__new__(cls)
            obj._constructor_args = (args, kwargs)
            return obj

        def deconstruct(obj):
            """
            Return a 3-tuple of class import path, positional arguments,
            and keyword arguments.
            """
            # Fallback version
            if path:
                module_name, _, name = path.rpartition('.')
            else:
                module_name = obj.__module__
                name = obj.__class__.__name__
            # Make sure it's actually there and not an inner class
            module = import_module(module_name)
            if not hasattr(module, name):
                raise ValueError(
                    "Could not find object %s in %s.\n"
                    "Please note that you cannot serialize things like inner "
                    "classes. Please move the object into the main module "
                    "body to use migrations.\n"
                    "For more information, see "
                    "https://docs.djangoproject.com/en/%s/topics/migrations/#serializing-values"
                    % (name, module_name, get_docs_version()))
            return (
                path or '%s.%s' % (obj.__class__.__module__, name),
                obj._constructor_args[0],
                obj._constructor_args[1],
            )


        klass.__new__ = staticmethod(__new__)
        # klass.__new__ = __new__

        # add deconstruct method to the new class
        klass.deconstruct = deconstruct

        return klass

    if not args:
        return decorator
    return decorator(*args)


# test class
@deconstructible
class A:
    def __init__(self, a, *args, c= None, **kwargs):
        self.a = a   
        self.c = c  

if __name__ =='__main__':
    a = A(10, c=100, f=10)
    p,args,kwargs = a.deconstruct() # __main__.A (10,) {'c': 100, 'f': 10}
    print(p, args, kwargs)

    b = A(5,c=10, f=200)
    pb, args_b, kwargs_b = A.deconstruct(b)
    print(pb, args_b, kwargs_b) # __main__.A (5,) {'c': 10, 'f': 200}

1 个答案:

答案 0 :(得分:1)

默认情况下该方法是静态的:

  

__new__()是一个静态方法(特殊情况,因此您无需这样声明),它将请求实例的类作为其第一个参数。

https://docs.python.org/3.4/reference/datamodel.html#object.new

因此staticmehthod中的klass.__new__ = staticmethod(__new__)只是要明确地说这是一个静态方法。