是否可以将 python 函数转换为 class?
Is it possible to convert a python function into a class?
我是 Python 的新手,来自 C++ 背景,这是我第一次看到一种只包含对象的语言。我刚刚了解到 class 和函数也只是对象。那么,有没有办法将以下函数转换为 class?
In [1]: def somefnc(a, b):
...: return a+b
...:
我首先尝试将 __call__
变量分配给 None
以从函数中删除 "callable nature"。但是正如您所看到的,__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]:
我不是为了开发目的而这样做,所以声称这是一种不好的做法没有任何意义。我只是想很好地理解 Python。当然,出于开发目的,我宁愿创建一个 class 而不是将一个函数转换为一个函数!
在剥夺函数将两个数字相加的能力后,我正在考虑通过修改 somefun.__dict__
将有效函数分配给属性 somefnc.__init__
和一些成员,以将其转换为 class。
在 Python 函数中是 function
class 的实例。所以我会给你一个关于任何 class 和实例的一般性答案。
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
在 Python 中,所有特殊方法(前缀和后缀中带有双下划线的方法)在通过运算符触发时从 class 访问,而不是从实例访问。
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
当按名称访问时,首先通过实例访问所有方法。差异是由于不同的搜索机制。当您按名称访问 method/attribute 时,您会调用 __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
如您所见,第一种情况下没有LOAD_ATTR
。 []
运算符被组装成一个特殊的虚拟机指令 BINARY_SUBSCR
。
我是 Python 的新手,来自 C++ 背景,这是我第一次看到一种只包含对象的语言。我刚刚了解到 class 和函数也只是对象。那么,有没有办法将以下函数转换为 class?
In [1]: def somefnc(a, b):
...: return a+b
...:
我首先尝试将 __call__
变量分配给 None
以从函数中删除 "callable nature"。但是正如您所看到的,__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]:
我不是为了开发目的而这样做,所以声称这是一种不好的做法没有任何意义。我只是想很好地理解 Python。当然,出于开发目的,我宁愿创建一个 class 而不是将一个函数转换为一个函数!
在剥夺函数将两个数字相加的能力后,我正在考虑通过修改 somefun.__dict__
将有效函数分配给属性 somefnc.__init__
和一些成员,以将其转换为 class。
在 Python 函数中是 function
class 的实例。所以我会给你一个关于任何 class 和实例的一般性答案。
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
在 Python 中,所有特殊方法(前缀和后缀中带有双下划线的方法)在通过运算符触发时从 class 访问,而不是从实例访问。
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
当按名称访问时,首先通过实例访问所有方法。差异是由于不同的搜索机制。当您按名称访问 method/attribute 时,您会调用 __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
如您所见,第一种情况下没有LOAD_ATTR
。 []
运算符被组装成一个特殊的虚拟机指令 BINARY_SUBSCR
。