简体   繁体   中英

Get class name in attribute definition

I need to make a mixin that knows the name of the class who is using it. Sort of like:

class FooMixin(...):
    bar = self.__class__

Except that self is not defined at attribute definition time. Is there a clean way to achieve this so it's transparent for the class who inherits the mixin?

At the time of definition of your mixin, nobody knows in which classes your mixin is used. You can only get the name dynamically in class methods by using 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"

Daniel's answer gives the reason why this is not possible in the declarative way you seem to like it - nobody knows at Mixin's definition-time where and when it will be used.

However, if you don't care about the time, but want the syntax , meaning you want to access bar defined as property in Mixin, and return self. class , this should work:

class classproperty(object):

    def __get__(self, instance, clazz):
        return clazz

class Mixin(object):

    bar = classproperty()


class Foo(Mixin):
    pass


print Foo().bar

First off, no special action is needed to know the name of a class:

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

similarly, no special action is needed to discover subclasses:

>>> MyMixin.__subclasses__()
[__main__.Foo, __main__.Bar]

If these aren't what you need, because you want to take action when your base class is subclassed, you need a 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'>,)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM