在属性定义中获取类名
我需要创建一个混合类(mixin),这个混合类能够知道使用它的类的名字。就像这样:
class FooMixin(...):
bar = self.__class__
不过在定义属性的时候,self
还没有被定义。有没有什么简单的方法可以做到这一点,让继承这个混合类的类使用起来感觉很自然呢?
3 个回答
1
首先,想要知道一个类的名字并不需要特别的操作:
class MyMixin(object):
def frob(self):
print "frobbing a", self.__class__.__name__
class Foo(MyMixin): pass
class Bar(MyMixin): pass
>>> Foo().frob()
frobbing a Foo
>>> Bar().frob()
frobbing a Bar
同样,想要找到子类也不需要做什么特别的事情:
>>> MyMixin.__subclasses__()
[__main__.Foo, __main__.Bar]
如果这些都不是你想要的,因为你想在你的基类被子类化的时候采取一些行动,那你就需要一个 metaclass( metaclass 是元类)!:
class MyMixinMeta(type):
def __init__(cls, name, bases, attrs):
if bases != (object,):
print name, cls, "is a subclass of", bases
class MyMixin(object):
__metaclass__ = MyMixinMeta
def frob(self):
print "frobbing a", self.__class__.__name__
>>> class Foo(MyMixin): pass
Foo <class '__main__.Foo'> is a subclass of (<class '__main__.MyMixin'>,)
>>> class Bar(MyMixin): pass
Bar <class '__main__.Bar'> is a subclass of (<class '__main__.MyMixin'>,)
1
Daniel的回答解释了为什么你想要的那种声明方式是行不通的——在定义Mixin的时候,没人知道它会在什么地方和什么时候被使用。
不过,如果你不在乎时间,只想要那种语法,也就是说你想要访问在Mixin中定义的属性bar,并返回self.class,那么这样做应该是可以的:
class classproperty(object):
def __get__(self, instance, clazz):
return clazz
class Mixin(object):
bar = classproperty()
class Foo(Mixin):
pass
print Foo().bar
3
在你定义这个混合类(mixin)的时候,没人知道这个混合类会被用在什么类里。你只能通过在类的方法里使用 self.__class__.__name__
来动态获取类的名字:
class FooMixin(object):
def some_method(self):
print "I'm in class %s" % self.__class__.__name__
class Main(FooMixin):
pass
instance = Main()
instance.some_method() # "I'm in class Main"