【发布时间】:2020-07-28 12:08:21
【问题描述】:
我有一个类,我在其中将几个类属性定义为对象。属性本身的名称是需要传递给对象的参数之一。目前它们是手动编写的,如下例所示:
class Beatles:
john = Guitar(name='john')
paul = Bass(name='paul')
george = Guitar(name='george')
ringo = Drums(name='ringo')
class Musician:
def __init__(self)
class Guitar(Musician):
def __init__(self, name)
class Bass(Musician):
def __init__(self, name)
class Drums(Musician):
def __init__(self, name)
我发现了一种解决方法,它使用元类使用 Foo 对象的命名空间字典来构建对象:
class Meta(type):
def __new__(cls, name, bases, dict_):
for k, v in dict_.items():
if isinstance(v, Musician):
dict_[k] = type(v)(k)
return super().__new__(cls, name, bases, dict_)
仅当“名称”参数是唯一不会出现这种情况的参数时才有效。有没有更好的办法?
【问题讨论】:
-
虽然问题本身具有技术价值,但这种设计存在固有问题。例如,当一个乐队有 2 个同名的音乐家时会发生什么?当然,您现在可以添加另一个检查,确保名称是唯一的并使用中间名进行更改。但是... a) 另一个很大的复杂性和 b) “Johnny B”不是一个有效的属性名称。在更大的意义上,是的,这是 Python 的一个问题。例如说一个表格。每个字段可能有一个名称,并且可能希望将它们分配给表单,但是 field.name 和 form.
. 之间没有链接 -
我想我在 Ramalho 的 Fluent Python 中看到了类似的东西,而且他没有明显的简单解决方案来桥接赋值
=运算符的左右两边,所以重复了这个名字。后来他确实提出了一些技巧,但是,IIRC 既不优雅,也不简单。除非你有压倒一切的理由去做这样的事情(比如成为框架内易用性的核心部分,将疣安全地隐藏在里面)然后,在你的位置上,我会去有了这个限制并解决它们。我怀疑这个问题也非常特定于 Python。
标签: python python-3.x oop metaclass