Python 使用 __slots__ 字典进行初始化是否有效?
Is it valid Python to use a __slots__ dictionary for initialization purposes?
在寻找初始化插槽的便捷方法时,我有一个 愚蠢的想法? wrongly? using __slots__
字典如下所示。
注意:有一个相关的 on SO where I've previously posted my idea as ,但我认为从中创建一个新问题可能更有用,因为我真的很想获得更多反馈。
因此,对于以下“技巧”,我将不胜感激 notes/advice/issues:
class Slotted:
__slots__ = {}
def __new__(cls, *args, **kwargs):
inst = super().__new__(cls)
for key, value in inst.__slots__.items():
setattr(inst, key, value)
return inst
class Magic(Slotted):
__slots__ = {
"foo": True,
"bar": 17
}
magic = Magic()
print(f"magic.foo = {magic.foo}")
print(f"magic.bar = {magic.bar}")
magic.foo = True
magic.bar = 17
是ok/safe要这样做吗?
有没有什么缺点或者可能的问题等等?
编辑:
在 Alex Waygood 提到 Python 3.8+ 中的文档目的之后,我提出了一个扩展,其中还包括对进一步子类化的更正 - 虽然现在它有点冗长:
class Slot(str):
__slots__ = ["init"]
def __new__(cls, init, doc=""):
obj = str.__new__(cls, doc)
obj.init = init
return obj
def __call__(self):
return self.init
class Slotted:
__slots__ = {}
def __new__(cls, *args, **kwargs):
obj = super().__new__(cls)
for base in reversed(cls.__mro__[:-1]):
if isinstance(base.__slots__, dict):
for key, value in base.__slots__.items():
if isinstance(value, Slot):
setattr(obj, key, value())
else:
raise TypeError(
f'Value for slot "{key}" must'
f' be of type "{Slot.__name__}"'
)
return obj
class Magic(Slotted):
"""This class is not so boring any more"""
__slots__ = {
"foo": Slot(2, doc="Some quite interesting integer"),
"bar": Slot(3.1416, doc="Some very exciting float")
}
help(Magic)
magic = Magic()
print(f"magic.__slots__ = {magic.__slots__}")
print(f"magic.foo = {magic.foo}")
print(f"magic.bar = {magic.bar}")
Help on class Magic in module __main__:
class Magic(Slotted)
| Magic(*args, **kwargs)
|
| This class is not so boring any more
|
| Method resolution order:
| Magic
| Slotted
| builtins.object
|
| Data descriptors defined here:
|
| bar
| Some very exciting float
|
| foo
| Some quite interesting integer
|
| ----------------------------------------------------------------------
| Static methods inherited from Slotted:
|
| __new__(cls, *args, **kwargs)
| Create and return a new object. See help(type) for accurate signature.
magic.__slots__ = {'foo': 'Some quite interesting integer', 'bar': 'Some very exciting float'}
magic.foo = 2
magic.bar = 3.1416
The docs 说 __slots__
允许任何包含字符串的迭代器,但它有一个关于映射的特定警告:
Any non-string iterable may be assigned to __slots__
. Mappings may also be used; however, in the future, special meaning may be assigned to the values corresponding to each key.
我不知道有任何活跃的提议将这种特殊含义添加到用于 __slots__
的映射中,但这并不意味着将来可能不会创建。当您在未来的版本中使用此代码时,我会留意弃用警告!
据我所知,将__slots__
定义为dict
的功能的预期用途是用于文档目的。
(我不知道这是在何处记录的,也不知道它是何时添加到 Python 中的。我知道这种行为在 [=37= 中是一致的] 3.8、3.9、3.10,实际上是 3.11 alpha 0,截至 2021 年 10 月 14 日。我还没有在 Python <= 3.7 上测试过它。)
如果我有 class Foo
,像这样:
class Foo:
"""The Foo class is for doing Foo-y things (obviously)."""
__slots__ = {
'bar': 'Some information about the bar attribute',
'baz': 'Some information about the baz attribute'
}
然后在交互式终端中调用 help(Foo)
会产生以下输出:
>>> help(Foo)
Help on class Foo in module __main__:
class Foo(builtins.object)
| The Foo class is for doing Foo-y things (obviously).
|
| Data descriptors defined here:
|
| bar
| Some information about the bar attribute
|
| baz
| Some information about the baz attribute
如果我在您的 Magic
class 上调用 help()
,但是,我得到以下输出:
>>> help(Magic)
Help on class Magic in module __main__:
class Magic(Slotted)
| Magic(*args, **kwargs)
|
| Method resolution order:
| Magic
| Slotted
| builtins.object
|
| Data descriptors defined here:
|
| bar
|
| foo
|
| ----------------------------------------------------------------------
| Static methods inherited from Slotted:
|
| __new__(cls, *args, **kwargs)
| Create and return a new object. See help(type) for accurate signature.
话虽如此——我认为没有任何地方表明您不能做您在问题中提出的那种事情。它似乎工作正常,所以如果你不太关心你的 class 的文档,它会让你的代码更枯燥,我建议你去吧!
在寻找初始化插槽的便捷方法时,我有一个 愚蠢的想法? wrongly? using __slots__
字典如下所示。
注意:有一个相关的
因此,对于以下“技巧”,我将不胜感激 notes/advice/issues:
class Slotted:
__slots__ = {}
def __new__(cls, *args, **kwargs):
inst = super().__new__(cls)
for key, value in inst.__slots__.items():
setattr(inst, key, value)
return inst
class Magic(Slotted):
__slots__ = {
"foo": True,
"bar": 17
}
magic = Magic()
print(f"magic.foo = {magic.foo}")
print(f"magic.bar = {magic.bar}")
magic.foo = True
magic.bar = 17
是ok/safe要这样做吗? 有没有什么缺点或者可能的问题等等?
编辑:
在 Alex Waygood 提到 Python 3.8+ 中的文档目的之后,我提出了一个扩展,其中还包括对进一步子类化的更正 - 虽然现在它有点冗长:
class Slot(str):
__slots__ = ["init"]
def __new__(cls, init, doc=""):
obj = str.__new__(cls, doc)
obj.init = init
return obj
def __call__(self):
return self.init
class Slotted:
__slots__ = {}
def __new__(cls, *args, **kwargs):
obj = super().__new__(cls)
for base in reversed(cls.__mro__[:-1]):
if isinstance(base.__slots__, dict):
for key, value in base.__slots__.items():
if isinstance(value, Slot):
setattr(obj, key, value())
else:
raise TypeError(
f'Value for slot "{key}" must'
f' be of type "{Slot.__name__}"'
)
return obj
class Magic(Slotted):
"""This class is not so boring any more"""
__slots__ = {
"foo": Slot(2, doc="Some quite interesting integer"),
"bar": Slot(3.1416, doc="Some very exciting float")
}
help(Magic)
magic = Magic()
print(f"magic.__slots__ = {magic.__slots__}")
print(f"magic.foo = {magic.foo}")
print(f"magic.bar = {magic.bar}")
Help on class Magic in module __main__:
class Magic(Slotted)
| Magic(*args, **kwargs)
|
| This class is not so boring any more
|
| Method resolution order:
| Magic
| Slotted
| builtins.object
|
| Data descriptors defined here:
|
| bar
| Some very exciting float
|
| foo
| Some quite interesting integer
|
| ----------------------------------------------------------------------
| Static methods inherited from Slotted:
|
| __new__(cls, *args, **kwargs)
| Create and return a new object. See help(type) for accurate signature.
magic.__slots__ = {'foo': 'Some quite interesting integer', 'bar': 'Some very exciting float'}
magic.foo = 2
magic.bar = 3.1416
The docs 说 __slots__
允许任何包含字符串的迭代器,但它有一个关于映射的特定警告:
Any non-string iterable may be assigned to
__slots__
. Mappings may also be used; however, in the future, special meaning may be assigned to the values corresponding to each key.
我不知道有任何活跃的提议将这种特殊含义添加到用于 __slots__
的映射中,但这并不意味着将来可能不会创建。当您在未来的版本中使用此代码时,我会留意弃用警告!
据我所知,将__slots__
定义为dict
的功能的预期用途是用于文档目的。
(我不知道这是在何处记录的,也不知道它是何时添加到 Python 中的。我知道这种行为在 [=37= 中是一致的] 3.8、3.9、3.10,实际上是 3.11 alpha 0,截至 2021 年 10 月 14 日。我还没有在 Python <= 3.7 上测试过它。)
如果我有 class Foo
,像这样:
class Foo:
"""The Foo class is for doing Foo-y things (obviously)."""
__slots__ = {
'bar': 'Some information about the bar attribute',
'baz': 'Some information about the baz attribute'
}
然后在交互式终端中调用 help(Foo)
会产生以下输出:
>>> help(Foo)
Help on class Foo in module __main__:
class Foo(builtins.object)
| The Foo class is for doing Foo-y things (obviously).
|
| Data descriptors defined here:
|
| bar
| Some information about the bar attribute
|
| baz
| Some information about the baz attribute
如果我在您的 Magic
class 上调用 help()
,但是,我得到以下输出:
>>> help(Magic)
Help on class Magic in module __main__:
class Magic(Slotted)
| Magic(*args, **kwargs)
|
| Method resolution order:
| Magic
| Slotted
| builtins.object
|
| Data descriptors defined here:
|
| bar
|
| foo
|
| ----------------------------------------------------------------------
| Static methods inherited from Slotted:
|
| __new__(cls, *args, **kwargs)
| Create and return a new object. See help(type) for accurate signature.
话虽如此——我认为没有任何地方表明您不能做您在问题中提出的那种事情。它似乎工作正常,所以如果你不太关心你的 class 的文档,它会让你的代码更枯燥,我建议你去吧!