2017-02-22 14 views
3

В методе экземпляра класса питона, я знаю, что мы можем получить имя класса с помощью self.__class__.__name__Сохранение имени класса в переменной класса без ввода имени класса?

Однако, я хотел бы сохранить имя класса в переменном классе, без кодирования на имя класс.

Я знаю, что может сделать это, чтобы получить имя класса в переменный классе:

class MyClass(object): 
    pass 
MyClass._myname = MyClass.__name__ 

Однако, я должен кодировать строковую MyClass два раз за пределами определения класса, просто чтобы получить имя класса в переменную класса. В этом случае, это было бы "MyClass", который я просто код может следующим образом:

class MyClass(object): 
    _myname = "MyClass" 

Но даже это является излишним, учитывая, что у меня есть код с жёстким "MyClass" в MyClass классе.

То, что я хотел бы, чтобы каким-то образом получить имя класса в переменную класса без кодирования имени класса, следующим образом:

class MyClass(object): 
    _myname = ???? # where ???? is a statement which returns the class 
       # name, in which the string "MyClass" does not appear 

даже возможно ли это?

ответ

5

Вы можете использовать декоратор

>>> def autoname(cls): 
... cls._MyName=cls.__name__ 
... return cls 
... 
>>> @autoname 
... class check: 
... pass 
... 
>>> check._MyName 
'check' 
>>> 

Или, если вы не хотите, чтобы жестко закодировать имя атрибута:

>>> def autoname2(name): 
...  def autoname(cls): 
...   setattr(cls, name, cls.__name__) 
...   return cls 
...  return autoname 
... 
>>> @autoname2('_StoreHere') 
... class check2: 
...  pass 
... 
>>> check2._StoreHere 
'check2' 
>>> 

Конечно, вторая форма может принимать несколько параметров, например:

>>> def autoname3(name, f=lambda x: x): 
...  def autoname(cls): 
...   setattr(cls, name, f(cls.__name__)) 
...   return cls 
...  return autoname 
... 
>>> @autoname3('_MyNameIs', lambda x: x.upper() + '_The_Bold') 
... class check3: 
...  pass 
... 
>>> check3._MyNameIs 
'CHECK3_The_Bold' 
>>> 

записку о декоратора против метакласса: Метаклассы серьезно круто, nonetheles s, если они им не нужны, их лучше избегать из-за печально известного metaclass conflicts.

3

Вы могли бы сделать это с метаклассом:

class NameMeta(type): 
    def __new__(meta, name, bases, dct): 
     dct['_name'] = name 
     return super().__new__(meta, name, bases, dct) 

class Foo(metaclass=NameMeta): 
    pass 

print(Foo._name)  # prints "Foo" 

Обратите внимание, что установка имени в качестве нового атрибута класса немного глупо, так как __name__ уже существует. Вероятно, вы должны изменить любой код, который вы пишете, который смотрит на атрибут _name и заставляет его искать __name__.

+0

Ну, на самом деле, я слишком упростил проблему. Я действительно хочу, чтобы переменная класса содержала некоторые данные, зависящие от имени класса ... другими словами, это было бы результатом функции имени класса. – HippoMan

+0

PS: Может ли вопрос поставить два ответа? Ответ от Bickkngt и ответ от Paul Panzer дают мне информацию, которую я ищу. Я хотел бы отметить оба ваших ответа, если это возможно. – HippoMan

+0

@ HippoMan Вы можете выдвигать оба. Но примите, я уверен, что вы можете только один. –