Sre*_*ram 3 python dynamic-languages python-3.x
我是来自 C++ 背景的 Python 新手,这是我第一次看到一种只包含对象的语言。我刚刚了解到类和函数也只是对象。那么,有没有办法将下面的函数转换为类呢?
In [1]: def somefnc(a, b):
...: return a+b
...:
Run Code Online (Sandbox Code Playgroud)
我首先尝试将__call__变量分配给以None消除函数的“可调用性质”。但正如您所看到的,已__call__成功替换为None但这并没有导致该函数在调用时停止添加数字,尽管在分配给somefnc.__call__(1,3)之前正在工作somefnc.__call__None
In [2]: somefnc.__dict__
Out[2]: {}
In [3]: somefnc.__call__
Out[3]: <method-wrapper '__call__' of function object at 0x7f282e8ff7b8>
In [4]: somefnc.__call__ = None
In [5]: x = somefnc(1, 2)
In [6]: print(x)
3
In [7]: somefnc.__call__
In [8]: print(somefnc.__call__(1, 2))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
ipython-input-8-407663da97ca
in <module>()
----> 1 print(somefnc.__call__(1, 2))
TypeError: 'NoneType' object is not callable
In [9]: print (somefnc(1,2))
3
In [10]:
Run Code Online (Sandbox Code Playgroud)
我这样做并不是为了开发目的,因此声称这是一种不好的做法是没有任何意义的。我只是想很好地理解Python。当然,出于开发目的,我宁愿创建一个类,也不愿将函数转换为函数!
在剥夺该函数添加两个数字的能力之后,我正在考虑somefnc.__init__通过修改 为该属性和一些成员分配一个有效的函数somefun.__dict__,以将其转换为类。
在 Python 中,函数是类的实例function。因此,我将为您提供有关任何类和实例的一般答案。
In [10]: class Test:
...: def __getitem__(self, i):
...: return i
...:
In [11]: t = Test()
In [12]: t[0]
Out[12]: 0
In [13]: t.__getitem__(0)
Out[13]: 0
In [14]: t.__getitem__ = None
In [15]: t[0]
Out[15]: 0
In [16]: t.__getitem__(0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-16-c72f91d2bfbc> in <module>()
----> 1 t.__getitem__(0)
TypeError: 'NoneType' object is not callable
Run Code Online (Sandbox Code Playgroud)
在Python中,所有特殊方法(前缀和后缀中带有双下划线的方法)在通过运算符触发时都是从类访问的,而不是从实例访问的。
In [17]: class Test2:
...: def test(self, i):
...: return i
...:
In [18]: t = Test2()
In [19]: t.test(1)
Out[19]: 1
In [20]: t.test = None
In [20]: t.test(1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-22-261b43cb55fe> in <module>()
----> 1 t.test(1)
TypeError: 'NoneType' object is not callable
Run Code Online (Sandbox Code Playgroud)
当通过名称访问时,所有方法首先通过实例访问。差异是由于不同的搜索机制造成的。当您按名称访问方法/属性时,__getattribute__默认情况下您调用的方法/属性将首先在实例的命名空间中搜索。当您通过运算符触发方法时,__getattribute__不会调用。你可以在反汇编中看到它。
In [22] import dis
In [23]: def test():
...: return Test()[0]
...:
In [24]: dis.dis(test)
2 0 LOAD_GLOBAL 0 (Test)
3 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
6 LOAD_CONST 1 (0)
9 BINARY_SUBSCR
10 RETURN_VALUE
In [25]: def test2():
...: return Test().__getitem__(0)
...:
In [26]: dis.dis(test2)
2 0 LOAD_GLOBAL 0 (Test)
3 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
6 LOAD_ATTR 1 (__getitem__)
9 LOAD_CONST 1 (0)
12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
15 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
LOAD_ATTR正如您所看到的,第一种情况没有。该[]运算符被汇编为特殊的虚拟机指令BINARY_SUBSCR。
| 归档时间: |
|
| 查看次数: |
3674 次 |
| 最近记录: |