Bir örneğin sınıf adını mı alıyorsunuz?


1437

Bunu yaptığım işlev örneğin sınıfının türetildiği temel sınıfsa, Python'da bir nesnenin örneğini oluşturan bir sınıf adını nasıl bulabilirim?

İnceleme modülünün burada bana yardımcı olabileceğini düşünüyordum , ama bana istediğimi vermiyor gibi görünüyor. Ve __class__üyeyi ayrıştırmadığından, bu bilgilere nasıl ulaşacağımdan emin değilim.


Sınıf değişkeninden tam olarak ne ayrıştırıyorsunuz ?
sykora

1
örneğin ait olduğu sınıfın en üst düzey adı (modül adı olmadan, vb.)
Dan

Ben tersi (yöntem / fonksiyon tanımlanmış sınıf almak için) yol daha zor olacağını düşünüyorum.
Alexey

Yanıtlar:


1908

Sınıfın __name__niteliğini denediniz mi? yani type(x).__name__sana sınıfın adını verecek, bence istediğin şey bu.

>>> import itertools
>>> x = itertools.count(0)
>>> type(x).__name__
'count'

Hala Python 2 kullanıyorsanız, yukarıdaki yöntemin yalnızca yeni stil sınıflarıyla çalıştığını unutmayın (Python 3 ve sonraki sürümlerinde tüm sınıflar "yeni stil" sınıflarıdır). Kodunuz bazı eski stil sınıfları kullanabilir. Her ikisi için de aşağıdakiler geçerlidir:

x.__class__.__name__

41
İnanılmaz derecede basit. Acaba neden dir(x.__class__)listelemiyor?
cfi

43
Neden yöntem __class__üzerinde typekullanılır? Gibi o kadar: type(x).__name__. Çifte alt çizgi üyelerini çağırmak doğrudan önerilmez? __name__Yine de kullanmanın bir yolunu göremiyorum .
jpmc26

25
__class__Eski tip sınıflarla uyumlu olmak için doğrudan kullanmalısınız , çünkü türleri sadece instance.
Quantum7

14
Bu genellikle günlük, orm ve çerçeve kodunda gerçekten yerleşik bir tür adı (x) olması gerektiği gibi kullanılır ... bir kullanıcının bir isim almak için "cesaretlere" bakmasını gerektiren çok pitonik değil, IMO.
Erik Aronesty

5
@ErikAronesty,def typename(x): return type(x).__name__
sleblanc

390

Sınıfın adını dize olarak istiyor musunuz?

instance.__class__.__name__

6
Veya sınıf nesnesini almak için örnek .__ class__: D
Pencilcheck

8
Çift alt çizgi özelliklerini kullanmak güvenli midir?
Eduard Luca

5
@EduardLuca neden güvenli olmasın? Yerleşik özellikler, yazdığınız kodla herhangi bir çakışmaya neden olmaması için alt çizgi kullanır
JC Rocamonde

3
Peki tek alt çizgi anlamına gelir / yöntem / özellik özel olması gerektiğini önermek (Python AFAIK gerçekten özel yöntemler uygulayamasanız da) ve ben de (bazı) çift alt çizgi ile durum böyle olmadığını merak ediyordum.
Eduard Luca

28
@EduardLuca Başlangıçtaki çift alt çizgi, başlangıçtaki tek bir alt çizgiye benzer, ancak daha da "özel" ("python ad yönetimi" konusuna bakın). Başlayarak her yıl çift alt çizgi ve sonunda farklıdır - bu piton için ayrılmıştır ve özel (__init__ ve __add__ gibi mesela sihirli yöntemleri) değildir.
Leagsaidh Gordon

101

type ()?

>>> class A(object):
...    def whoami(self):
...       print type(self).__name__
...
>>>
>>> class B(A):
...    pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>

Bu sınıf üyesi ile aynı , ancak bu sonucu elle, biraz sinir bozucu ayrıştırmak zorunda ...
Dan

8
Bunu beğendim. Bu şekilde, bir temel sınıfta alt sınıfın adını almak mümkündür.
joctee

6
veya aynı davranışı elde etmek self.__class__.__name__yerine type(self).__name__. type()İşlev farkında olmadığım bir şey olmadığı sürece ?
andreb

2
Eğer kullanıyorsanız type(item)bir liste öğesinin üzerine sonuç olacak <type 'instance'>ise item.__class__.__name__sınıf adını almıştır.
Grochni

1
@Grochni'nin bahsettiği sorunun sadece Python 2.x'teki belirli sınıflar için geçerli olduğunu düşünüyorum, buraya bakın: stackoverflow.com/questions/6666856/…
Nate CK

43
class A:
  pass

a = A()
str(a.__class__)

Yukarıdaki örnek kod (etkileşimli yorumlayıcıda girdi olduğunda) , özellik çağrıldığında üretilen kodun '__main__.A'aksine 'A'üretilir __name__. Basitçe sonucunu geçerek A.__class__için strayrıştırma sizin için işlenir yapıcısı. Ancak, daha açık bir şey istiyorsanız aşağıdaki kodu da kullanabilirsiniz.

"{0}.{1}".format(a.__class__.__module__,a.__class__.__name__)

Ayrı modüllerde aynı ada sahip sınıflarınız varsa, bu davranış tercih edilebilir.

Yukarıda verilen örnek kod Python 2.7.5'te test edilmiştir.


2.6.6'da test edilmiştir. Hala iyi çalışıyor.
Hamlett

29
type(instance).__name__ != instance.__class__.__name  #if class A is defined like
class A():
   ...

type(instance) == instance.__class__                  #if class A is defined like
class A(object):
  ...

Misal:

>>> class aclass(object):
...   pass
...
>>> a = aclass()
>>> type(a)
<class '__main__.aclass'>
>>> a.__class__
<class '__main__.aclass'>
>>>
>>> type(a).__name__
'aclass'
>>>
>>> a.__class__.__name__
'aclass'
>>>


>>> class bclass():
...   pass
...
>>> b = bclass()
>>>
>>> type(b)
<type 'instance'>
>>> b.__class__
<class __main__.bclass at 0xb765047c>
>>> type(b).__name__
'instance'
>>>
>>> b.__class__.__name__
'bclass'
>>>

5
Bu sadece eski Python 2.x için geçerlidir. 3.x'te, bclass () yöntemi bclass (nesne) olarak çözülür. Ve o zaman bile, Python 2.2'de yeni sınıflar ortaya çıktı.
alcalde

16

İyi soru.

İşte birisine yardım edebilecek GHZ'lere dayanan basit bir örnek:

>>> class person(object):
        def init(self,name):
            self.name=name
        def info(self)
            print "My name is {0}, I am a {1}".format(self.name,self.__class__.__name__)
>>> bob = person(name='Robert')
>>> bob.info()
My name is Robert, I am a person

13

Alternatif olarak classmethoddekoratörü kullanabilirsiniz :

class A:
    @classmethod
    def get_classname(cls):
        return cls.__name__

    def use_classname(self):
        return self.get_classname()

Kullanımı :

>>> A.get_classname()
'A'
>>> a = A()
>>> a.get_classname()
'A'
>>> a.use_classname()
'A'

10

Özel __name__niteliği kavramanın yanı sıra, kendinizi belirli bir sınıf / işlev için nitelikli isme ihtiyaç duyabilirsiniz . Bu, türleri yakalayarak yapılır __qualname__.

Çoğu durumda, bunlar tamamen aynı olacaktır, ancak iç içe sınıflarla / yöntemlerle uğraşırken, bunlar elde ettiğiniz çıktıda farklılık gösterir. Örneğin:

class Spam:
    def meth(self):
        pass
    class Bar:
        pass

>>> s = Spam()
>>> type(s).__name__ 
'Spam'
>>> type(s).__qualname__
'Spam'
>>> type(s).Bar.__name__       # type not needed here
'Bar'
>>> type(s).Bar.__qualname__   # type not needed here 
'Spam.Bar'
>>> type(s).meth.__name__
'meth'
>>> type(s).meth.__qualname__
'Spam.meth'

İç gözlem, peşinde olduğunuz şey olduğundan, bu her zaman göz önünde bulundurmak isteyebilirsiniz.


2
__qualname__Unutulmamalıdır ki Python 3.3+
FireAphis

10
Ve benim yazılım "meth" bir şey adlandırmaktan kaçınır.
Bobort

__qualname__Vs için ilgili açıklama __name__: stackoverflow.com/questions/58108488/what-is-qualname-in-python
ti7

0

Örnek sınıf adı almak için:

type(instance).__name__

veya

instance.__class__.__name__

ikisi de aynı

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.