我正在尝试设计一个类结构,其中类的基础在运行时确定。非常感谢the answer to this question about metaclasses,它点击了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,))
从这里可以看出,classname只是供人类使用的任意字符串,Python认为如果我想去迷惑自己,我很欢迎。
这是对的吗?如果允许不同的类共享相同的名称,那么在Python的其他地方是否有等待我的陷阱?
答案 0 :(得分:4)
我无法评论您为什么要这样做,但如果您确实需要这样的动态行为,或许可以考虑使用metaclass来实现目标?
无论如何,如果你想知道使用相同的类名是否会在以后引起问题(我假设你的意思是除了可维护性之外的问题 - 正如其他人所说的那样,这个很容易混淆和不必要的复杂),然后不,它不会。
documentation for type()
非常清楚参数的用途:
名称字符串是类名,并成为
__name__
属性; 基元元组列出基类并成为__bases__
属性;并且dict字典是包含的命名空间 类body的定义,并成为__dict__
属性
该说明显示该名称仅用于填充__name__
字段。事实证明,它基本上适用于人类,如in another answer所示。
事实上,您甚至不需要使用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,))
答案 1 :(得分:3)
类名不需要与存储它的变量的名称有任何关系。您可以使用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将没有任何问题。但是,那些必须维护代码的人可能会这样做。