2011-08-04 17 views
66

Şu anda bulunduğum sınıfın adını nasıl alabilirim?Mevcut dersin adını aldınız mı?

Örnek:

def get_input(class_name): 
    [do things] 
    return class_name_result 

class foo(): 
    input = get_input([class name goes here]) 

nedeniyle I (vistrails) ile arabirim am programın doğası gereği, ben input başlatmak için __init__() kullanamazsınız.

cevap

18

Bir sınıfın gövdesinde, sınıf adı henüz tanımlanmadı, bu nedenle kullanılabilir değil. Sadece sınıfın adını yazamaz mısın? Belki de problem hakkında daha fazla şey söylemelisiniz, böylece sizin için bir çözüm bulabiliriz.

Bu işi sizin için yapacak bir metaclass oluşturacağım. Sınıf oluşturma zamanında çağrılır (kavramsal olarak sınıfın en sonunda: blok) ve yaratılan sınıfı manipüle edebilir. Bunu test etmedim:

cls_name = self.__class__.__name__ 

DÜZENLEME: As Ned Batcheler söylediği

, bu işe yaramaz

class InputAssigningMetaclass(type): 
    def __new__(cls, name, bases, attrs): 
     cls.input = get_input(name) 
     return super(MyType, cls).__new__(cls, name, bases, newattrs) 

class MyBaseFoo(object): 
    __metaclass__ = InputAssigningMetaclass 

class foo(MyBaseFoo): 
    # etc, no need to create 'input' 

class foo2(MyBaseFoo): 
    # etc, no need to create 'input' 
+0

ben yapmaya çalışıyorum netleştirmek iÇİN: bir yöntemin bir sınıf değişkeni, 'giriş', ** dışını oluşturmak ve başlatmak için gereken **. Her biri, sınıf adı olarak parametre olarak "get_input" olarak adlandırması gereken bir grup küçük sınıfa sahibim. Bunu genelleştirmeye çalışıyorum, böylece her sınıfa gitmek zorunda değilim (100 tane olacak) ve dersin adını yazmam gerekmiyor. –

+0

Tamam, cevabımı yardımcı olması gereken bir metaclass ile güncelledim. –

+0

'InputAssigningMetaclass' içinde' süper 'satırında 'MyType' ne anlama gelir? –

12

Sınıfın gizli özellikleridir erişebilirsiniz sınıf bedeninde, ama bir yöntemde olurdu.

99

obj.__class__.__name__ size herhangi bir nesne adını alacak, bu nedenle bunu yapabilirsiniz:

class Clazz(): 
    def getName(self): 
     return self.__class__.__name__ 

Kullanımı:

>>> c = Clazz() 
>>> c.getName() 
'Clazz' 
+0

Bu neden kabul edilen cevap değil? DÜZENLEME: Tamam OP'nin kapsamı iç değil, sınıf seviyesinde. – KomodoDave

+1

@KomodoDave, çünkü bu yanlıştır, yöntem kapsamında bile. Bir alt sınıftan 'getName 'çağırdığınızda, alt sınıf adı çıkar. Eğer çalışmakta olduğunuz dersi gerçekten istiyorsanız, o zaman zorlaşır. –

+0

@KenetJervet Bir _parent_ sınıfından 'getName' dediğinizde, çocuk sınıfının adı çıkacak mı? Bunu işaret ettiğin için sorun yok. – KomodoDave

7

DÜZENLEME: Evet, yapabilirsiniz; ama hile yapmak zorundasınız: Şu anda çalışan sınıf adı çağrı yığında bulunur ve traceback modülü yığına erişmenizi sağlar.

>>> import traceback 
>>> def get_input(class_name): 
...  return class_name.encode('rot13') 
... 
>>> class foo(object): 
...  _name = traceback.extract_stack()[-1][2] 
...  input = get_input(_name) 
... 
>>> 
>>> foo.input 
'sbb' 

Ancak, bunu yapmazdım; Orijinal cevabım hala bir çözüm olarak kendi tercihim. Orijinal cevap:

muhtemelen çok basit çözüm (dekoratörler kara büyü yeteneğine sahiptir, ancak metaclasses antik, okült kara büyü yeteneğine sahip metaclasses içeren Ned'in cevap benzeyen, ancak daha az güçlü bir dekoratör, kullanmaktır)

>>> def get_input(class_name): 
...  return class_name.encode('rot13') 
... 
>>> def inputize(cls): 
...  cls.input = get_input(cls.__name__) 
...  return cls 
... 
>>> @inputize 
... class foo(object): 
...  pass 
... 
>>> foo.input 
'sbb' 
>>> 
1
import sys 

def class_meta(frame): 
    class_context = '__module__' in frame.f_locals 
    assert class_context, 'Frame is not a class context' 

    module_name = frame.f_locals['__module__'] 
    class_name = frame.f_code.co_name 
    return module_name, class_name 

def print_class_path(): 
    print('%s.%s' % class_meta(sys._getframe(1))) 

class MyClass(object): 
    print_class_path() 
İlgili konular