名称在同一模块中具有不同基数的两个类?

时间:2014-03-16 03:02:13

标签: python inheritance types metaclass classname

我正在尝试设计一个类结构,其中类的基础在运行时确定。非常感谢the answer to this question about metaclasses,它点击了type函数可以通过在运行时构造基元的元组来实现这一点。优异。

现在这开启了一种可能性,我不确定我是否感到满意 - 通过一系列的操作,我可以找到相当于:

X  = type('X', (object,), {})
Y  = type('Y', (X,), {})
Y2 = type('Y', (object,), {})

我现在有两个类(YY2)具有不同的继承结构,但它们都共享类名'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的其他地方是否有等待我的陷阱?

2 个答案:

答案 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

在此代码之后,FooBar变量引用了两个名为DecoratedClass的类,它们具有不同的继承层次结构。

Python对类名没有特别的意义。它主要供人类使用。如果你这样做,Python将没有任何问题。但是,那些必须维护代码的人可能会这样做。