添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
至今单身的伏特加  ·  QTreeWidget ...·  1 月前    · 
霸气的酸菜鱼  ·  Ubuntu 安装postgresql - ...·  2 月前    · 
奔跑的足球  ·  页面未找到 - 七牛云·  11 月前    · 

它应该给出一个错误。

5 个评论
Try @staticmethod
在这种情况下,为什么它会成为类的一部分?它应该是函数
你可以实现你自己的描述符来做这个。但为什么呢?
这似乎是一件非常奇怪的事情。 大多数 Python 程序都知道他们可以通过使用一个适当类型的实例来调用一个静态方法。 写 self.my_static_method() 比写 MyClassName.my_static_method() 要简单得多。 你的用例是什么?
替换代码0】是模块中的一个函数,不是一个静态方法。
python
python-3.x
function
class
class-method
U12-Forward
U12-Forward
发布于 2021-09-20
2 个回答
MisterMiyagi
MisterMiyagi
发布于 2021-09-20
已采纳
0 人赞同

替换代码0】、 staticmethod 以及普通方法如何被查询/绑定的功能是通过以下方式实现的 descriptors .同样地,我们可以定义一个描述符,即 forbids 在一个实例上进行查找/绑定。

这种描述符的天真实现会检查它是否通过一个实例来查找,在这种情况下会引发一个错误。

class NoInstanceMethod:
    """Descriptor to forbid that other descriptors can be looked up on an instance"""
    def __init__(self, descr, name=None):
        self.descr = descr
        self.name = name
    def __set_name__(self, owner, name):
        self.name = name
    def __get__(self, instance, owner):
        # enforce the instance cannot look up the attribute at all
        if instance is not None:
            raise AttributeError(f"{type(instance).__name__!r} has no attribute {self.name!r}")
        # invoke any descriptor we are wrapping
        return self.descr.__get__(instance, owner)

这可以应用于其他描述符之上,以防止它们在一个实例上被查询到。特别是,它可以与classmethodstaticmethod相结合,以防止在一个实例上使用它们。

class A:
    def __init__(self, a):
        self.a = a
    @NoInstanceMethod
    @classmethod
    def foo(cls):
        return 'hello world!'
A.foo()     # Stdout: hello world!
A(1).foo()  # AttributeError: 'A' object has no attribute 'foo'

上面的NoInstanceMethod是 "天真 "的,因为它没有考虑到将__get__以外的描述符调用传播到它的包装描述符。例如,我们可以传播__set_name__的调用,让被包裹的描述符知道它的名字。

由于描述符可以自由地(不)实现任何描述符的方法,所以可以支持,但需要适当的错误处理。扩展NoInstanceMethod以支持实践中需要的任何描述符方法。

Niel Godfrey Ponciano
Niel Godfrey Ponciano
发布于 2021-09-20
0 人赞同

一个变通方法是在类对象初始化时覆盖其值,以确保它不会被 self 调用。

def raise_(exc):
    raise exc
class A:
    STRICTLY_CLASS_METHODS = [
        "foo",
    def __init__(self, a):
        self.a = a
        for method in self.STRICTLY_CLASS_METHODS:
            # Option 1: Using generator.throw() to raise exception. See https://www.python.org/dev/peps/pep-0342/#new-generator-method-throw-type-value-none-traceback-none
            # setattr(self, method, lambda *args, **kwargs: (_ for _ in ()).throw(AttributeError(method)))
            # Option 2: Using a function to raise exception
            setattr(self, method, lambda *args, **kwargs: raise_(AttributeError(method)))
    @classmethod
    def foo(cls):
        return 'hello world!'
    def bar(self):
        return 'hola mundo!', self.a

Output

>>> A.foo()
'hello world!'
>>> a = A(123)
>>> a.bar()
('hola mundo!', 123)
>>> a.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 11, in <lambda>
  File "<stdin>", line 2, in raise_
AttributeError: foo
>>> a.bar()
('hola mundo!', 123)
>>> A(45).bar()
('hola mundo!', 45)
>>> A(6789).foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 11, in <lambda>