Bir nesnenin niteliklerini listeleme


330

Bir sınıf örneğinde var olan özniteliklerin bir listesini almanın bir yolu var mı?

class new_class():
    def __init__(self, number):
        self.multi = int(number) * 2
        self.str = str(number)

a = new_class(2)
print(', '.join(a.SOMETHING))

İstenen sonuç "multi, str" çıktısı alınacaktır. Bu bir komut dosyasının çeşitli bölümlerinden geçerli özniteliklerini görmek istiyorum.


75
Hemen hemen Python'daki herkes sınıflarını adlandırır NewClass. Gibi bir adlandırma kuralı kullanırsanız, insanların beklentilerini karşılayabilirsiniz new_class.
Mike Graham

İnsan etkileşimli olmasına ve programlı olarak kullanılamamasına rağmen, help()işlev sınıflar, işlevler, yerleşik
yapılar


Yanıtların hiçbiri neden 'Kabul Edildi' olarak işaretlenmiyor?
pfabri

Yanıtlar:


295
>>> class new_class():
...   def __init__(self, number):
...     self.multi = int(number) * 2
...     self.str = str(number)
... 
>>> a = new_class(2)
>>> a.__dict__
{'multi': 4, 'str': '2'}
>>> a.__dict__.keys()
dict_keys(['multi', 'str'])

Ayrıca pprint'i yararlı bulabilirsiniz .


29
Dikte kullanımı sorunu r / python'da ortaya çıktı. birisi vars (a) 'nın a .__ dict__ ile eşdeğer olduğuna dikkat çekti
David

5
Herkesin merak etmesi durumunda, bu Python 2.7 üzerinde de çalışır
Ben Mordecai

8
Spesifik pprint.pprint(a.__dict__)olarak, özniteliklere güzel bir baskı yapar.
smci

1
Kesinlikle bu pprintPython 2.6 üzerinde çalışmaz.
John Greene

3
Bunun yalnızca kullanıcı tanımlı sınıflar için geçerli olduğunu, yerleşik veya uzantı türleri için geçerli olmadığını unutmayın.
ivan_pozdeev

173
dir(instance)
# or (same value)
instance.__dir__()
# or
instance.__dict__

Daha sonra, hangi türün olduğunu type()veya bir yöntem olup olmadığını test edebilirsiniz callable().


dir aşırı yüklenmiş niteliği olan sınıflarda daha iyi çalıştı get / set
ogurets

dir (örnek), muhtemelen ilgilenmediğiniz bir çok şeyi listeler
jciloa

Bu bana bostonsklearn veri kümesindeki tüm mevcut özellikleri kazandıran tek işlevdi - __dict__boştu, aslında 5 mevcut özellik vardı
Coruscate5


53

Önceki tüm cevaplar doğrudur, sorduğunuz şey için üç seçeneğiniz vardır

  1. dir()

  2. vars()

  3. __dict__

>>> dir(a)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'multi', 'str']
>>> vars(a)
{'multi': 4, 'str': '2'}
>>> a.__dict__
{'multi': 4, 'str': '2'}

1
vars(foo)dönerfoo.__dict__
Boris

32
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

Bu elbette sınıf tanımındaki tüm yöntemleri veya nitelikleri basacaktır. "Özel" yöntemleri i.startwith('__'),i.startwith('_')


24

Kontrol modülü bir nesne incelemek için kolay bir yol sunar:

Denetleme modülü, modüller, sınıflar, yöntemler, işlevler, geri izleme, çerçeve nesneleri ve kod nesneleri gibi canlı nesneler hakkında bilgi almanıza yardımcı olacak çeşitli kullanışlı işlevler sağlar.


getmembers()Bunu kullanarak sınıfınızın tüm niteliklerini ve değerlerini görebilirsiniz. Özel veya korumalı özellikleri hariç tutmak için kullanın .startswith('_'). Dışlamak için yöntemler veya işlevleri kullanmak inspect.ismethod()veya inspect.isfunction().

import inspect


class NewClass(object):
    def __init__(self, number):
        self.multi = int(number) * 2
        self.str = str(number)

    def func_1(self):
        pass


a = NewClass(2)

for i in inspect.getmembers(a):
    # Ignores anything starting with underscore 
    # (that is, private and protected attributes)
    if not i[0].startswith('_'):
        # Ignores methods
        if not inspect.ismethod(i[1]):
            print(i)

Not ismethod()ikinci elemanı kullanılır iilk olduğundan, sadece bir dize (Adından) 'dir.

Offtopic: Sınıf adları için CamelCase kullanın .


13

Sen kullanabilirsiniz dir(your_object)özelliklerini elde etmek ve getattr(your_object, your_object_attr)değerlerini almak için

kullanım:

for att in dir(your_object):
    print (att, getattr(your_object,att))

Bu özellikle nesnenizde __dict__ yoksa kullanışlıdır. Eğer durum böyle değilse, var (nesne) öğenizi de deneyebilirsiniz.


11

Sıklıkla, kullanmanız gereken özelliklerin tam bir listesini listelemekten bahsedilir dir(). Bununla birlikte, popüler inanışın aksine tüm nitelikleri dir()ortaya koymadığını unutmayın. Örneğin , sınıfın kendisinden erişebilseniz bile , bir sınıfın girişinde eksik olabileceğini fark edebilirsiniz. ( Python 2 , Python 3 ) üzerindeki dokümandan :__name__dir()dir()

Dir () öncelikle etkileşimli bir istemde kullanım kolaylığı olarak sağlandığından, titiz veya tutarlı bir şekilde tanımlanmış bir ad kümesi sağlamaya çalıştığından daha ilginç bir ad kümesi sağlamaya çalışır ve ayrıntılı davranışı sürümler arasında değişebilir. Örneğin, bağımsız değişken bir sınıf olduğunda, metaclass öznitelikleri sonuç listesinde değildir.

Aşağıdaki gibi bir işlev daha eksiksiz olma eğilimindedir, ancak tamlık garantisi yoktur, çünkü döndürülen liste yöntemi dir()uygulamak, __dir__()özelleştirmek __getattr__()veya __getattribute__()sınıfta veya ebeveynlerinden birinde olmak üzere birçok faktörden etkilenebilir . Daha fazla ayrıntı için sağlanan bağlantılara bakın.

def dirmore(instance):
    visible = dir(instance)
    visible += [a for a in set(dir(type)).difference(visible)
                if hasattr(instance, a)]
    return sorted(visible)

9

Bunun için ne istiyorsun? Niyetinizi bilmeden size en iyi yanıtı almak zor olabilir.

  • Sınıfınızın bir örneğini belirli bir şekilde görüntülemek istiyorsanız bunu manuel olarak yapmak neredeyse her zaman daha iyidir. Bu, tam olarak ne istediğinizi içerecek ve istemediklerinizi içermeyecek ve sipariş öngörülebilir olacaktır.

    Bir sınıfın içeriğini görüntülemenin bir yolunu arıyorsanız, önem verdiğiniz nitelikleri manuel olarak biçimlendirin ve bunu sınıfınız için __str__veya __repr__yöntemi olarak sağlayın.

  • Bir nesnenin nasıl çalıştığını anlaması için hangi yöntemlerin ve bu türlerin var olduğunu öğrenmek istiyorsanız, kullanın help. help(a)dokümanı temel alarak nesnenin sınıfı hakkında biçimlendirilmiş bir çıktı gösterir.

  • dirbir nesnenin tüm niteliklerini programlı olarak almak için vardır. (Erişim __dict__, aynı şekilde gruplayacağım ancak kendimi kullanmayacağım bir şey yapar.) Ancak, bu istediğiniz şeyleri içermeyebilir ve istemediğiniz şeyleri içerebilir. Güvenilmez ve insanlar bunu daha sık istediklerini düşünüyorlar.

  • Biraz ortogonal bir notta, şu anda Python 3 için çok az destek var. Gerçek yazılım yazmakla ilgileniyorsanız, numpy, lxml, Twisted, PIL veya Python 3'ü henüz desteklemeyen ve çok yakında herhangi bir zamanda planınız olmayan herhangi bir sayıda web çerçevesi gibi üçüncü taraf şeyler isteyeceksiniz. 2.6 ve 3.x dalı arasındaki farklar küçüktür, ancak kütüphane desteğindeki fark çok büyüktür.


4
Sadece beş yıl sonra (şimdi), bahsettiğiniz tüm üçüncü taraf modüllerinin python3'ü desteklediğine inanıyorum. Kaynak: python3wos.appspot.com
pzkpfw

8

Bunu yapmanın birden fazla yolu var:

#! /usr/bin/env python3
#
# This demonstrates how to pick the attiributes of an object

class C(object) :

  def __init__ (self, name="q" ):
    self.q = name
    self.m = "y?"

c = C()

print ( dir(c) )

Çalıştırıldığında, bu kod üretir:

jeffs@jeff-desktop:~/skyset$ python3 attributes.py 
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',      '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'm', 'q']

jeffs@jeff-desktop:~/skyset$

2
Bu cevap neden reddedildi? Hata ayıklama amacıyla, dir oldukça iyi çalışır!
Dunatotatos

Pretty Python 2.7.x ile çalışır. Tam olarak ne istediğimi.
Davidson Lima

7

Lütfen sırayla yürütülen python kabuk komut dosyasına bakın, burada bir sınıfın özelliklerini dize biçiminde virgülle ayırarak alacaksınız.

>>> class new_class():
...     def __init__(self, number):
...         self.multi = int(number)*2
...         self.str = str(number)
... 
>>> a = new_class(4)
>>> ",".join(a.__dict__.keys())
'str,multi'<br/>

3.4 python kullanıyorum


Ve sadece liste sadece isterseniz kullanabilirsiniz a.__dict__.keys(). Ancak, bir nesnenin belirli bir niteliği olup olmadığını bilmek istiyorsanız kullanabilirsiniz hasattr.
berna1111

4

Bu cevaplara ek olarak, herhangi bir değerin neredeyse tüm yapısını ortaya çıkarmak için bir işlev (python 3) ekleyeceğim. O kullanır dir, sonra özellik adları tam listesini kurmak için kullandığı getattrher isimde. Değerin her üyesinin türünü görüntüler ve mümkün olduğunda tüm üyeyi de görüntüler:

import json

def get_info(obj):

  type_name = type(obj).__name__
  print('Value is of type {}!'.format(type_name))
  prop_names = dir(obj)

  for prop_name in prop_names:
    prop_val = getattr(obj, prop_name)
    prop_val_type_name = type(prop_val).__name__
    print('{} has property "{}" of type "{}"'.format(type_name, prop_name, prop_val_type_name))

    try:
      val_as_str = json.dumps([ prop_val ], indent=2)[1:-1]
      print('  Here\'s the {} value: {}'.format(prop_name, val_as_str))
    except:
      pass

Şimdi aşağıdakilerden herhangi biri fikir vermelidir:

get_info(None)
get_info('hello')

import numpy
get_info(numpy)
# ... etc.

Vay canına, bu bir mücevher!
pfabri

evet bu bir cankurtaran. Neden bu listeleri kolayca açamadım ve yeterince türün "tuple" türünde " yuvaları " olduğundan emin olamadım: İşte yuva değeri: ["nsname", "hostmaster", "serial", "refresh", "yeniden deneme", "süresi doluyor", "minttl", "ttl"]
Mik R

3

Bir nesnenin niteliklerini alma

class new_class():
    def __init__(self, number):
    self.multi = int(number) * 2
    self.str = str(number)

new_object = new_class(2)                
print(dir(new_object))                   #total list attributes of new_object
attr_value = new_object.__dict__         
print(attr_value)                        #Dictionary of attribute and value for new_class                   

for attr in attr_value:                  #attributes on  new_class
    print(attr)

Çıktı

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__','__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'multi', 'str']

{'multi': 4, 'str': '2'}

multi
str

1

Kullanmadan önce yazıldığı gibi obj.__dict__yaygın vakaları işleyebilir, ancak bazı sınıflar bu __dict__özelliğe ve kullanıma sahip değildir __slots__(çoğunlukla bellek verimliliği için).

Bunu yapmanın daha esnek bir yolu için örnek:

class A(object):
    __slots__ = ('x', 'y', )
    def __init__(self, x, y):
        self.x = x
        self.y = y


class B(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y


def get_object_attrs(obj):
    try:
        return obj.__dict__
    except AttributeError:
        return {attr: getattr(obj, attr) for attr in obj.__slots__}


a = A(1,2)
b = B(1,2)
assert not hasattr(a, '__dict__')

print(get_object_attrs(a))
print(get_object_attrs(b))

bu kodun çıktısı:

{'x': 1, 'y': 2}
{'x': 1, 'y': 2}

Not1:
Python dinamik bir dildir ve öznitelikleri almaya çalıştığınız sınıfları bilmek her zaman daha iyidir, çünkü bu kod bile bazı durumları kaçırabilir.

Not2:
Bu kod yalnızca sınıf değişkenleri sağlanmayan örnek değişkenleri verir. Örneğin:

class A(object):
    url = 'http://stackoverflow.com'
    def __init__(self, path):
        self.path = path

print(A('/questions').__dict__)

kod çıkışları:

{'path': '/questions'}

Bu kod, urlsınıf niteliğini yazdırmaz ve istenen sınıf niteliklerini atlayabilir.
Bazen bir özelliğin bir örnek üyesi olduğunu düşünebiliriz, ancak bu örnek kullanılarak gösterilmez ve gösterilmez.


2
Bir sınıf olabilir __dict__ ve __slots__ bu yüzden muhtemelen sadece dikte yerine her ikisini de denemek istersiniz.
cz

1
  • Kullanıyor __dict__veya vars çalışmıyor çünkü özlüyor __slots__.
  • Kullanıyor __dict__ve __slots__ çalışmıyor çünkü __slots__temel sınıflardan kaçıyor.
  • Yöntemler veya özellikler gibi sınıf özniteliklerinin yanı sıra nesne özniteliklerini de içerdiğinden, kullanma dir işe yaramaz .
  • Kullanmak vars, kullanmaya eşdeğerdir __dict__.

Bu sahip olduğum en iyisi:

from typing import Dict

def get_attrs( x : object ) -> Dict[str, object]:
    mro      = type( x ).mro()
    attrs    = { }
    has_dict = False
    sentinel = object()

    for klass in mro:
        for slot in getattr( klass, "__slots__", () ):
            v = getattr( x, slot, sentinel )

            if v is sentinel:
                continue

            if slot == "__dict__":
                assert not has_dict, "Multiple __dicts__?"
                attrs.update( v )
                has_dict = True
            else:
                attrs[slot] = v

    if not has_dict:
        attrs.update( getattr( x, "__dict__", { } ) )

    return attrs

Bu işlevi spome basit sınıfa uygulayalım: class C: def __init __ (self): print ("create") i = 42 Kodunuz neden bu sınıf için boş liste veriyor? (Yani o = C () sonra get_attrs (o) boşsa) Ayrıca get_attrs ("mystr") için yaptı
ged

0
attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()]

Büyük harf veya tek alt çizgi ile başlayan sınıf öznitelik adlarıyla çalışmaz.
fviktor

0

Lütfen aşağıdaki Python kabuğu komut dosyası yürütme işlemine sırayla bakın, sınıfın oluşturulmasından örneklerin alan adlarının çıkarılmasına kadar çözüm verecektir.

>>> class Details:
...       def __init__(self,name,age):
...           self.name=name
...           self.age =age
...       def show_details(self):
...           if self.name:
...              print "Name : ",self.name
...           else:
...              print "Name : ","_"
...           if self.age:
...              if self.age>0:
...                 print "Age  : ",self.age
...              else:
...                 print "Age can't be -ve"
...           else:
...              print "Age  : ","_"
... 
>>> my_details = Details("Rishikesh",24)
>>> 
>>> print my_details
<__main__.Details instance at 0x10e2e77e8>
>>> 
>>> print my_details.name
Rishikesh
>>> print my_details.age
24
>>> 
>>> my_details.show_details()
Name :  Rishikesh
Age  :  24
>>> 
>>> person1 = Details("",34)
>>> person1.name
''
>>> person1.age
34
>>> person1.show_details
<bound method Details.show_details of <__main__.Details instance at 0x10e2e7758>>
>>> 
>>> person1.show_details()
Name :  _
Age  :  34
>>>
>>> person2 = Details("Rob Pike",0)
>>> person2.name
'Rob Pike'
>>> 
>>> person2.age
0
>>> 
>>> person2.show_details()
Name :  Rob Pike
Age  :  _
>>> 
>>> person3 = Details("Rob Pike",-45)
>>> 
>>> person3.name
'Rob Pike'
>>> 
>>> person3.age
-45
>>> 
>>> person3.show_details()
Name :  Rob Pike
Age can't be -ve
>>>
>>> person3.__dict__
{'age': -45, 'name': 'Rob Pike'}
>>>
>>> person3.__dict__.keys()
['age', 'name']
>>>
>>> person3.__dict__.values()
[-45, 'Rob Pike']
>>>

Ayrıca her bir özelliğin callablilty'sini de kontrol edebiliriz. Stackoverflow.com/questions/1398022/…
hygull

-4

__attr__ bir örneğin özniteliklerinin listesini verir.

>>> import requests
>>> r=requests.get('http://www.google.com')
>>> r.__attrs__
['_content', 'status_code', 'headers', 'url', 'history', 'encoding', 'reason', 'cookies', 'elapsed', 'request']
>>> r.url
'http://www.google.com/'
>>>

Her zaman çalışmaz. Ayrıca, __attr__açıklama yazabilirsiniz ancak __attrs__kodda kullanın . Ne de benim için çalıştı (werkzeug.datastructures.FileStorage)
Jonas
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.