同模块中两个类同名但基类不同?
我正在尝试设计一个类的结构,让类的基类在运行时决定。非常感谢关于元类的问题的回答,我明白了可以通过在运行时构建基类的元组来使用type
函数。太棒了。
这让我想到一个我不太确定是否能接受的可能性——通过一系列操作,我可能会得到类似于:
X = type('X', (object,), {})
Y = type('Y', (X,), {})
Y2 = type('Y', (object,), {})
现在我有两个类(Y
和Y2
),它们的继承结构不同,但它们的类名都是'Y'
。
c = y.__class__
c2 = y2.__class__
(c,c2) #returns (__main__.Y, __main__.Y)
(c.__bases__,c2.__bases__) #returns ((__main__.X,), (object,))
从这里看,类名似乎只是一个供人类使用的任意字符串,而Python的态度是,如果我想让自己困惑,那就随便我。
这样理解对吗?如果不同的类可以共享相同的名字,Python的其他地方会有潜在的问题吗?
2 个回答
类的名字和你用来存储它的变量名没有必要有任何关系。你可以通过一个 class
语句和一个赋值来实现相同的效果:
class Y(Base1): pass
Y2 = Y
class Y(Base2): pass
在实际操作中,像装饰器这样的东西就会出现这种情况,如果你不更新返回对象的元数据:
def decorate(klass):
class DecoratedClass(klass):
def stuff(self):
do_whatever()
return klass
@decorate
class Foo(object): pass
@decorate
class Bar(object): pass
在这段代码执行后,Foo
和 Bar
这两个变量分别指向两个名为 DecoratedClass
的类,但它们的继承结构是不同的。
Python 对类名没有特别的要求。类名主要是给人类看的。如果你这样做,Python 是不会有问题的。不过,维护代码的人可能会觉得麻烦。
我不能评论你为什么想这样做,但如果你确实需要这种动态的行为,也许可以考虑使用元类来实现你的目标?
无论如何,如果你在担心使用相同的类名会不会在以后造成问题(我假设你指的不是可维护性的问题——正如其他人所说,这样做很可能会让事情变得混乱和复杂),那么答案是不会的。
关于type()
的文档对参数的说明很清楚:
名称字符串是类名,并成为
__name__
属性;基类元组列出了基类,并成为__bases__
属性;字典则是包含类体定义的命名空间,并成为__dict__
属性。
这个描述表明,名称只是用来填充__name__
字段。实际上,这基本上是为了人类理解,如另一条回答所示。
事实上,你甚至不需要使用type()
来做到这一点——你可以直接用简单的class
语句来实现。
class X(object): pass
class Y(object): pass
def create_other_y():
class Y(X): pass
global Y2
Y2 = Y
create_other_y()
(Y, Y2) # => (__main__.Y, __main__.Y)
(Y.__bases__, Y2.__bases__) # => ((object,), (__main__.X,))