Mevcut sınıfın adını al?


103

Şu anda bulunduğum sınıfın adını nasıl alabilirim?

Misal:

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

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

Arayüz kurduğum programın doğası gereği (vistrails), __init__()başlatmak için kullanamıyorum input.

Yanıtlar:


159

obj.__class__.__name__ size herhangi bir nesne adı alacak, böylece bunu yapabilirsiniz:

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

Kullanım:

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

1
Neden bu kabul edilen cevap değil? DÜZENLEME: Tamam OP'nin kapsamı içsel değil, sınıf düzeyinde.
KomodoDave

6
@KomodoDave, çünkü yöntem kapsamında bile bu yanlış. Bir getNamealt sınıftan aradığınızda , alt sınıf adını verir. Daha sonra birlikte çalıştığınız sınıfı GERÇEKTEN istiyorsanız zorlaşır.
Kenet Jervet

@KenetJervet getNameBir ebeveyn sınıfından aradığınızda , alt sınıf adını çıktı olarak vereceğini mi söylüyorsunuz ? Bunu işaret ettiğin için tamam.
KomodoDave

5
OO terimlerinde, çözüm ( getName()yöntem bir üst sınıfta tanımlanmış olsa bile gerçek çalışma zamanı alt sınıf adını döndürmek ) doğrudur.
sxc731

22

Bir sınıfın gövdesinde, sınıf adı henüz tanımlanmamıştır, bu nedenle mevcut değildir. Sadece sınıfın adını yazamaz mısın? Belki de sizin için bir çözüm bulabilmemiz için sorun hakkında daha fazla şey söylemeniz gerekir.

Bu işi sizin için yapmak için bir metasınıf yaratırdım. Sınıf oluşturma zamanında çağrılır (kavramsal olarak sınıfın en sonunda: blok) ve oluşturulmakta olan sınıfı değiştirebilir. Bunu test etmedim:

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'

Ne yapmaya çalıştığımı açıklığa kavuşturmak için: Bir yöntemin dışında bir sınıf değişkeni, 'girdi' oluşturmam ve başlatmam gerekiyor . Her biri kendi sınıf adını parametre olarak kullanarak 'get_input' çağırması gereken bir sürü küçük sınıfım var. Bunu genellemeye çalışıyorum, böylece her sınıfa gitmeme (100 kadar olacak) ve sınıfın adını yazmam gerekmeyecek.
Jonathan Ginsburg

Tamam, cevabımı yardımcı olabilecek bir meta sınıfla güncelledim.
Ned Batchelder

1
Neyi MyTypede superhat InputAssigningMetaclassbakın?
A.

16

Buna sınıfın özel nitelikleri ile erişebilirsiniz:

cls_name = self.__class__.__name__

DÜZENLE:

Söylediği gibi Ned Batcheler, bu sınıf bedeninde işe yaramaz, ancak bir yöntemde işe yarar.


12

__qualname__Python 3.3'te uygulanan PEP 3155 tanıtıldı .

Üst düzey işlevler ve sınıflar için, __qualname__öznitelik özniteliğe eşittir __name__. Yuvalanmış sınıflar, yöntemler ve iç içe geçmiş işlevler için, __qualname__öznitelik, modülün üst düzeyinden nesneye giden noktalı bir yol içerir.

Bir sınıfın veya bir işlevin tanımının içinden erişilebilir, bu nedenle örneğin:

class Foo:
    print(__qualname__)

etkili bir şekilde yazdıracaktır Foo. Tam olarak nitelenmiş adı (modülün adı hariç) alacaksınız, bu yüzden onu .karaktere bölmek isteyebilirsiniz .

Bununla birlikte, tanımlanmakta olan sınıfın gerçek bir şekilde ele alınmasının bir yolu yoktur.

>>> class Foo:
...     print('Foo' in globals())
... 
False

7

DÜZENLEME: Evet, yapabilirsiniz; ancak hile yapmanız gerekir: Şu anda çalışan sınıf adı çağrı yığınında mevcuttur ve tracebackmodül yığına erişmenize izin verir.

>>> 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, çözüm olarak hala kendi tercihimdir. Orijinal cevap:

Muhtemelen en basit çözüm, Ned'in meta sınıfları içeren cevabına benzer, ancak daha az güçlü olan bir dekoratör kullanmaktır (dekoratörler kara büyü yapabilir, ancak metasınıflar eski, gizli kara büyü yeteneğine sahiptir )

>>> 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()

1

Bence şöyle olmalı:

    class foo():
        input = get_input(__qualname__)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.