Python 静态方法并不总是可调用的

编程入门 行业动态 更新时间:2024-10-24 22:30:35
本文介绍了Python 静态方法并不总是可调用的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

使用 __dict__,我的@staticmethod 不是 callable.

Python 2.7.5(默认,2016 年 8 月 29 日,10:12:21)[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] 在 linux2输入帮助"、版权"、信用"或许可"以获取更多信息.>>>从 __future__ 导入(absolute_import、除法、print_function)>>>C类(对象):... @staticmethod...定义 foo():...对于名称,C.__dict__.items() 中的 val:...如果名称[:2] != '__':...打印(名称,可调用(val),类型(val))...>>>C.foo()foo False

  • 这怎么可能?
  • 如何检查静态方法是否可调用?

我在下面提供了一个更详细的例子:

脚本 test.py

from __future__ import (absolute_import, Division, print_function)C类(对象):@静态方法定义 foo():返回 42定义栏(自我):print('bar() 是否可以调用?', callable(C.bar))打印('foo()是否可调用?',可调用(C.foo))对于属性,C.__dict__.items() 中的值:如果属性 [:2] != '__':打印(属性,'\t',可调用(值),'\t',类型(值))c = C()c.bar()

python2 的结果

>python2.7 test.pybar() 可以调用吗?真的foo() 是可调用的吗?真的bar True <type 'function'>foo False

python3 的结果相同

>python3.4 test.pybar() 可以调用吗?真的foo() 是可调用的吗?真的bar True foo False

解决方案

这种行为的原因是描述符协议.C.foo 不会返回 staticmethod 而是一个普通函数,而 __dict__ 中的 'foo' 是一个 staticmethod(和 staticmethod 是一个描述符).

简而言之 C.foo 在这种情况下与 C.__dict__['foo'] 不同 - 而是 C.__dict__['foo'].__get__(C)(另请参阅 描述符上的数据模型):

>>>callable(C.__dict__['foo'].__get__(C))真的>>>类型(C.__dict__['foo'].__get__(C))功能>>>可调用(C.foo)真的>>>类型(C.foo)功能>>>C.foo 是 C.__dict__['foo'].__get__(C)真的

在您的情况下,我会使用 getattr 检查可调用对象(知道描述符以及如何访问它们)而不是存储在 __dict__ 类中的值:

def bar(self):print('bar() 是否可以调用?', callable(C.bar))打印('foo()是否可调用?',可调用(C.foo))对于 C.__dict__.keys() 中的属性:如果属性 [:2] != '__':value = getattr(C, 属性)打印(属性,'\t',可调用(值),'\t',类型(值))

打印(在 python-3.x 上):

bar() 是否可以调用?真的foo() 是可调用的吗?真的bar True foo True

python-2.x 的类型不同,但是 callable 的结果是一样的:

bar() 是否可以调用?真的foo() 是可调用的吗?真的bar True <type 'instancemethod'>foo True <type 'function'>

While parsing attributes using __dict__, my @staticmethod is not callable.

Python 2.7.5 (default, Aug 29 2016, 10:12:21) [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from __future__ import (absolute_import, division, print_function) >>> class C(object): ... @staticmethod ... def foo(): ... for name, val in C.__dict__.items(): ... if name[:2] != '__': ... print(name, callable(val), type(val)) ... >>> C.foo() foo False <type 'staticmethod'>

  • How is this possible?
  • How to check if a static method is callable?

I provide below a more detailed example:

Script test.py

from __future__ import (absolute_import, division, print_function) class C(object): @staticmethod def foo(): return 42 def bar(self): print('Is bar() callable?', callable(C.bar)) print('Is foo() callable?', callable(C.foo)) for attribute, value in C.__dict__.items(): if attribute[:2] != '__': print(attribute, '\t', callable(value), '\t', type(value)) c = C() c.bar()

Result for python2

> python2.7 test.py Is bar() callable? True Is foo() callable? True bar True <type 'function'> foo False <type 'staticmethod'>

Same result for python3

> python3.4 test.py Is bar() callable? True Is foo() callable? True bar True <class 'function'> foo False <class 'staticmethod'>

解决方案

The reason for this behavior is the descriptor protocol. The C.foo won't return a staticmethod but a normal function while the 'foo' in __dict__ is a staticmethod (and staticmethod is a descriptor).

In short C.foo isn't the same as C.__dict__['foo'] in this case - but rather C.__dict__['foo'].__get__(C) (see also the section in the documentation of the Data model on descriptors):

>>> callable(C.__dict__['foo'].__get__(C)) True >>> type(C.__dict__['foo'].__get__(C)) function >>> callable(C.foo) True >>> type(C.foo) function >>> C.foo is C.__dict__['foo'].__get__(C) True

In your case I would check for callables using getattr (which knows about descriptors and how to access them) instead of what is stored as value in the class __dict__:

def bar(self): print('Is bar() callable?', callable(C.bar)) print('Is foo() callable?', callable(C.foo)) for attribute in C.__dict__.keys(): if attribute[:2] != '__': value = getattr(C, attribute) print(attribute, '\t', callable(value), '\t', type(value))

Which prints (on python-3.x):

Is bar() callable? True Is foo() callable? True bar True <class 'function'> foo True <class 'function'>

The types are different on python-2.x but the result of callable is the same:

Is bar() callable? True Is foo() callable? True bar True <type 'instancemethod'> foo True <type 'function'>

更多推荐

Python 静态方法并不总是可调用的

本文发布于:2023-11-27 06:38:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1636991.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:静态   方法   Python

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!