考虑以下令人厌恶的类:
class MapInt:
__call__ = int
def __sub__(self, other):
return map(self, other)
__add__ = map
Run Code Online (Sandbox Code Playgroud)
然后可以map(int, lst)通过调用MapInt() - lst,即
assert list(MapInt() - ['1','2','3'])) == [1,2,3] # passes
Run Code Online (Sandbox Code Playgroud)
然而,加法就不那么合作了:
assert list(MapInt() + ['1','2','3'])) == [1,2,3] # TypeError: map() must have at least two arguments.
Run Code Online (Sandbox Code Playgroud)
这个奇怪的现象可以通过直接调用magic方法来解决:
assert list(MapInt.__add__(MapInt(), ['1','2','3'])) == [1,2,3] # passes
assert list(MapInt().__add__(MapInt(), ['1','2','3'])) == [1,2,3] # passes
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,什么给出了?直接赋值__add__似乎“丢弃”了self参数,但是调用方法本身或以标准方式定义它效果很好。
@classmethod在 Python 3.9 中,我们获得了链接和@property合理创建类属性的能力。
class Foo:\n @property\n def instance_property(self):\n return "A regular property"\n\n @classmethod\n @property\n def class_property(cls):\n return "A class property"\nRun Code Online (Sandbox Code Playgroud)\n这是通过与描述符协议进行适当的交互来实现的@classmethod,这意味着一个人的前景不仅限于@property阳光下的任何描述符。一切都很好,直到发现该实现导致了“许多下游问题”,并在 Python 3.11 中弃用。
我已经阅读了一些关于弃用的GitHub 讨论,并且不会在这里抱怨我所说的仓促撤回仓促设计。事实上,类属性是人们想要的合理的东西,并且可以在 Python 3.9/3.10 中使用,但现在不能。发行说明建议如下:
\n\n\n要 \xe2\x80\x9cpass-through\xe2\x80\x9d 类方法,请考虑使用 Python 3.10 中添加的 __wrapped__ 属性。
\n
如果说这样的句子本身极其无益,那就不会引起争议。描述符协议不是普通用户需要或想要遇到的东西,因此@classmethod通过自定义实现与它们链接肯定是那些了解情况的人可以并且会花时间弄清楚如何在 3.11+ 中正确执行的操作。
但是对于那些不知道@property除了允许他们删除括号的东西之外还有什么的人来说,如何在 Python 3.11+ 中定义类属性,特别是如何做得好?
python properties python-3.x python-decorators python-descriptors