为什么不需要staticmethod装饰器?

jia Jimmy

我正在尝试使用类装饰器来实现单例模式,如下所示:

python3.6+


def single_class(cls):

    cls._instance = None
    origin_new = cls.__new__

    # @staticmethod
    # why staticmethod decorator is not needed here?
    def new_(cls, *args, **kwargs):
        if cls._instance:
            return cls._instance
        cls._instance = cv = origin_new(cls)
        return cv

    cls.__new__ = new_

    return cls


@single_class
class A():
    ...


a = A()
b = A()

print(a is b ) # True

单例模式似乎运行良好,但是我想知道为什么在我的代码中@staticmethod不需要在函数上方new_,因为我知道这cls.__new__是一个静态方法。


class object:
    """ The most base type """
    ...
    @staticmethod # known case of __new__
    def __new__(cls, *more): # known special case of object.__new__
        """ Create and return a new object.  See help(type) for accurate signature. """
        pass
    ...

使用更新测试 python2.7+

@staticmethod似乎有需要的py2和不需要的py3


def single_class(cls):

    cls._instance = None
    origin_new = cls.__new__

    # @staticmethod
    # without @staticmethod there will be a TypeError 
    # and work fine with @staticmethod adding
    def new_(cls, *args, **kwargs):
        if cls._instance:
            return cls._instance
        cls._instance = cv = origin_new(cls)
        return cv

    cls.__new__ = new_

    return cls


@single_class
class A(object):
    pass


a = A()
b = A()

print(a is b ) 

# TypeError: unbound method new_() must be called with A instance as the first argument (got type instance instead)

阿米特·特里帕蒂(Amit Tripathi)

__new__明确地将类实例作为其第一个参数。__new__如其他答案中所述,这是一种特殊情况,并且使其成为静态方法的可能原因是允许使用new创建其他类:

super(CurrentClass, cls).__new__(otherCls, *args, **kwargs)

您的代码@staticmethod没有装饰器的情况下在Python 3中工作但在Python 2中不工作的原因是因为Python 2和Python 3允许类的方法访问的方式不同。

Python 3 [ 2 ]中没有无限方法当您尝试在Python 3上访问类方法时,您会获得一个函数,而在Python 2中,您将获得无限方法。如果您这样做,则可以看到此信息:

# Python 2
>>> A.__new__
<unbound method A.new_>

# Python 3
>>> A.__new__
<function __main__.single_class.<locals>.new_(cls, *args, **kwargs)>

Python 2中,您的装饰器等于,single_class.__new__(A)但是由于它__new__是一个未绑定的方法,因此您不能使用类本身来调用它。您需要一个类实例,但是为此,您需要创建您的类(catch-22),这就是为什么需要staticmethod的原因。错误消息说的是同样的话unbound method new_() must be called with A instance as first argument

Python 3 __new__中,您可以使用A类本身来调用它。因此,single_class.__new__(A)将工作。


本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么for循环不需要可变的迭代器?

为什么链接器正在寻找不需要的库

为什么不需要开玩笑?

为什么“ typeof”不需要括号?

* ngFor为什么不需要括号?

为什么编译器需要.java后缀,但解释器不需要.class后缀?

为什么数据集的foreach方法不需要编码器,而map需要?

为什么C编程需要编译器而shell脚本不需要?

为什么Java需要接口而Smalltalk不需要接口?

为什么`head`需要`()`和`shape`不需要?

为什么在使用GLFW时不需要加载着色器?

为什么 JavaScript for 循环中的迭代器不需要分号?

为什么SIP服务器不需要此INVITE的授权?

为什么我的f:selectItems不需要自定义转换器?

为什么我不需要在邮件中指定SMTP服务器?

为什么后增量不需要复制而预增量不需要复制

什么是 For 循环?为什么在 R 中不需要它?

为什么我的 DLL 不需要 DllMain 函数?

为什么我的Keras LSTM中不需要TimeDistributed?

为什么OpenVPN启用我不需要的路由?

Logrotate:“日志不需要旋转”为什么?

为什么在结束“循环”时“中断”不需要分号?

为什么调用不需要类的进口的方法?

为什么JavaScript在函数声明后不需要分号?

为什么我在这里不需要SFINAE

为什么Kotlin打印声明不需要范围说明?

为什么节点使用不需要导入?

为什么在此示例代码中不需要 readSync?

为什么 Go 链码不需要注解?