Daftar atribut suatu objek

330

Apakah ada cara untuk mengambil daftar atribut yang ada pada instance kelas?

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

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

Hasil yang diinginkan adalah "multi, str" akan menjadi output. Saya ingin ini melihat atribut saat ini dari berbagai bagian skrip.

MadSc13ntist
sumber
75
Hampir semua orang di Python menamakan kelas mereka seperti NewClass. Anda dapat menentang harapan orang-orang jika Anda menggunakan konvensi penamaan seperti new_class.
Mike Graham
Meskipun bersifat interaktif manusia dan tidak dapat digunakan secara terprogram, help()fungsi membantu untuk mendapatkan info tentang kelas, fungsi, builtin, modul, dan lainnya
ytpillai
1
Relevan: stackoverflow.com/questions/1398022/…
sancho.s ReinstateMonicaCellio
Mengapa tidak ada jawaban yang ditandai sebagai 'Diterima'?
pfabri

Jawaban:

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'])

Anda juga dapat menemukan cetakan sangat membantu.


sumber
29
Masalah penggunaan dikt hanya muncul di r / python. seseorang menunjukkan bahwa vars (a) setara dengan .__ dict__
David
5
Jika ada yang bertanya-tanya, ini bekerja pada Python 2.7 juga
Ben Mordecai
8
Untuk lebih spesifik, pprint.pprint(a.__dict__)lakukan print cantik pada atribut.
smci
1
Jelas itu pprintTIDAK bekerja pada Python 2.6.
John Greene
3
Perhatikan bahwa ini hanya berfungsi untuk kelas yang ditentukan pengguna, bukan untuk tipe bawaan atau ekstensi.
ivan_pozdeev
173
dir(instance)
# or (same value)
instance.__dir__()
# or
instance.__dict__

Kemudian Anda bisa menguji dengan tipe apa type()atau apakah metode dengan callable().

Htechno
sumber
dir bekerja lebih baik di kelas dengan atribut kelebihan / set
oguret
dir (instance) daftar banyak hal yang Anda mungkin tidak tertarik
jciloa
Ini adalah satu-satunya fungsi yang membuat saya semua atribut yang tersedia pada bostondataset dari sklearn - __dict__kosong, padahal sebenarnya ada 5 atribut yang tersedia
Coruscate5
72

vars(obj) mengembalikan atribut suatu objek.

rohithpr
sumber
54

Semua jawaban sebelumnya benar, Anda memiliki tiga opsi untuk apa yang Anda minta

  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'}
grepit
sumber
1
vars(foo)kembalifoo.__dict__
Boris
32
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

Ini tentu saja akan mencetak metode atau atribut apa pun dalam definisi kelas. Anda dapat mengecualikan metode "pribadi" dengan mengubah i.startwith('__')kei.startwith('_')

SilentGhost
sumber
24

The memeriksa modul menyediakan cara mudah untuk memeriksa suatu objek:

Modul inspect menyediakan beberapa fungsi yang berguna untuk membantu mendapatkan informasi tentang objek langsung seperti modul, kelas, metode, fungsi, traceback, objek bingkai, dan objek kode.


Dengan menggunakan getmembers()Anda dapat melihat semua atribut kelas Anda, beserta nilainya. Untuk mengecualikan atribut pribadi atau yang dilindungi gunakan .startswith('_'). Untuk mengecualikan metode atau fungsi, gunakan inspect.ismethod()atau 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)

Catatan yang ismethod()digunakan pada elemen kedua isejak yang pertama hanyalah string (namanya).

Offtopic: Gunakan CamelCase untuk nama kelas.

Fermi paradox
sumber
13

Anda bisa menggunakan dir(your_object)untuk mendapatkan atribut dan getattr(your_object, your_object_attr)untuk mendapatkan nilai

penggunaan:

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

Ini sangat berguna jika objek Anda tidak memiliki __dict__. Jika tidak, Anda dapat mencoba var (objek_Anda) juga

Jason Angel
sumber
11

Sering disebutkan bahwa untuk membuat daftar atribut lengkap yang harus Anda gunakan dir(). Namun perlu dicatat bahwa bertentangan dengan kepercayaan populer dir()tidak membawa semua atribut. Misalnya, Anda mungkin memperhatikan bahwa __name__mungkin ada yang hilang dari daftar kelas dir()meskipun Anda dapat mengaksesnya dari kelas itu sendiri. Dari dokumen pada dir()( Python 2 , Python 3 ):

Karena dir () disediakan terutama sebagai kenyamanan untuk digunakan pada prompt interaktif, ia mencoba untuk memasok satu set nama yang menarik lebih banyak daripada mencoba untuk memasok serangkaian nama yang didefinisikan secara ketat atau konsisten, dan perilakunya yang terperinci dapat berubah antar rilis. Misalnya, atribut metaclass tidak ada dalam daftar hasil ketika argumennya adalah kelas.

Fungsi seperti berikut cenderung lebih lengkap, meskipun tidak ada jaminan kelengkapan karena daftar yang dikembalikan oleh dir()dapat dipengaruhi oleh banyak faktor termasuk menerapkan __dir__()metode, atau menyesuaikan __getattr__()atau __getattribute__()di kelas atau salah satu dari orang tuanya. Lihat tautan yang disediakan untuk detail lebih lanjut.

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

Untuk apa Anda menginginkan ini? Mungkin sulit untuk memberi Anda jawaban terbaik tanpa mengetahui maksud pasti Anda.

  • Hampir selalu lebih baik untuk melakukan ini secara manual jika Anda ingin menampilkan instance kelas Anda dengan cara tertentu. Ini akan mencakup apa yang Anda inginkan dan tidak termasuk apa yang tidak Anda inginkan, dan urutannya dapat diprediksi.

    Jika Anda mencari cara untuk menampilkan konten kelas, secara manual format atribut yang Anda pedulikan dan berikan ini sebagai __str__atau __repr__metode untuk kelas Anda.

  • Jika Anda ingin mempelajari tentang metode apa dan yang ada untuk objek untuk memahami cara kerjanya, gunakan help. help(a)akan menampilkan output terformat tentang kelas objek berdasarkan dokumennya.

  • dirada untuk mendapatkan semua atribut objek secara terprogram. (Mengakses __dict__melakukan sesuatu yang saya kelompokkan sebagai sama tetapi saya tidak akan menggunakan diri saya sendiri.) Namun, ini mungkin tidak termasuk hal-hal yang Anda inginkan dan itu mungkin termasuk hal-hal yang tidak Anda inginkan. Itu tidak dapat diandalkan dan orang berpikir mereka menginginkannya lebih sering daripada yang mereka lakukan.

  • Pada catatan yang agak ortogonal, ada sangat sedikit dukungan untuk Python 3 saat ini. Jika Anda tertarik untuk menulis perangkat lunak nyata Anda akan menginginkan hal-hal pihak ketiga seperti numpy, lxml, Twisted, PIL, atau sejumlah kerangka kerja web yang belum mendukung Python 3 dan tidak memiliki rencana terlalu cepat. Perbedaan antara 2.6 dan cabang 3.x kecil, tetapi perbedaan dalam dukungan perpustakaan sangat besar.

Mike Graham
sumber
4
Saya hanya ingin menunjukkan bahwa lima tahun kemudian (sekarang), saya percaya semua modul pihak ketiga yang Anda sebutkan mendukung python3. Sumber: python3wos.appspot.com
pzkpfw
8

Ada lebih dari satu cara untuk melakukannya:

#! /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) )

Saat dijalankan, kode ini menghasilkan:

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$
pengguna1928764
sumber
2
Mengapa jawaban ini tidak dipilih? Untuk tujuan debug, dir berfungsi dengan baik!
Dunatotatos
Cukup bagus dengan Python 2.7.x. Apa yang saya inginkan.
Davidson Lima
7

Silakan lihat skrip shell python yang telah dieksekusi secara berurutan, di sini Anda akan mendapatkan atribut kelas dalam format string yang dipisahkan oleh koma.

>>> 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/>

Saya menggunakan python 3.4

Lokesh kumar
sumber
Dan kalau mau hanya daftar bisa pakai saja a.__dict__.keys(). Namun jika Anda ingin tahu apakah suatu objek memiliki atribut tertentu yang dapat Anda gunakan hasattr.
berna1111
4

Selain jawaban ini, saya akan menyertakan fungsi (python 3) untuk memuntahkan hampir seluruh struktur nilai apa pun. Ini digunakan diruntuk membuat daftar lengkap nama properti, lalu gunakan getattrdengan masing-masing nama. Ini menampilkan jenis setiap anggota dari nilai, dan bila mungkin juga menampilkan seluruh anggota:

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

Sekarang, salah satu dari yang berikut ini harus memberi wawasan:

get_info(None)
get_info('hello')

import numpy
get_info(numpy)
# ... etc.
Gershom
sumber
Wow, itu permata!
pfabri
ya ini adalah penyelamat. tidak tahu mengapa ini saya tidak dapat dengan mudah membongkar daftar ini dan cukup yakin memiliki jenis " slot " dari tipe "tuple" Berikut adalah nilai slot : ["nsname", "hostmaster", "serial", "refresh", "coba lagi", "kedaluwarsa", "minttl", "ttl"]
Mik R
3

Dapatkan atribut dari suatu objek

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)

Keluaran

['__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
Diberkati
sumber
1

Seperti yang ditulis sebelum menggunakan obj.__dict__dapat menangani kasus umum tetapi beberapa kelas tidak memiliki __dict__atribut dan penggunaan __slots__(kebanyakan untuk efisiensi memori).

contoh untuk cara yang lebih tangguh dalam melakukan ini:

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

output kode ini:

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

Catatan1:
Python adalah bahasa yang dinamis dan selalu lebih baik mengetahui kelas yang Anda coba dapatkan atributnya karena bahkan kode ini dapat melewatkan beberapa kasus.

Note2:
kode ini hanya menghasilkan variabel instan yang berarti variabel kelas tidak disediakan. sebagai contoh:

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

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

output kode:

{'path': '/questions'}

Kode ini tidak mencetak urlatribut class dan mungkin menghilangkan atribut class yang diinginkan.
Terkadang kita mungkin berpikir bahwa atribut adalah anggota instan tetapi tidak dan tidak akan ditampilkan menggunakan contoh ini.

ShmulikA
sumber
2
Sebuah kelas dapat memiliki __dict__ dan __slots__ , jadi Anda mungkin ingin mencoba keduanya bukan hanya dict.
cz
1
  • Menggunakan __dict__atau vars tidak berfungsi karena ketinggalan __slots__.
  • Menggunakan __dict__dan __slots__ tidak berfungsi karena ketinggalan __slots__dari kelas dasar.
  • Menggunakan dir tidak berfungsi karena termasuk atribut kelas, seperti metode atau properti, serta atribut objek.
  • Menggunakan varssama dengan menggunakan __dict__.

Ini yang terbaik yang saya miliki:

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
cz
sumber
Mari kita terapkan fungsi ini pada kelas sederhana: kelas C: def __init __ (mandiri): print ("dibuat") i = 42 Mengapa kode Anda memberikan daftar kosong untuk kelas seperti itu? (Maksud saya jika o = C () maka get_attrs (o) kosong) Ini juga berlaku untuk get_attrs ("mystr")
ged
0
attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()]
shammerw0w
sumber
Itu tidak bekerja dengan nama atribut kelas yang dimulai dengan huruf kapital atau garis bawah tunggal.
fviktor
0

Silakan lihat eksekusi scripting shell Python berikut secara berurutan, itu akan memberikan solusi dari penciptaan kelas untuk mengekstraksi nama field instance.

>>> 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']
>>>
camar
sumber
Kami juga dapat memeriksa kemungkinan panggilan dari setiap atribut.kunjungi stackoverflow.com/questions/1398022/…
hygull
-4

__attr__ memberikan daftar atribut instance.

>>> 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/'
>>>
Vivek
sumber
Tidak selalu berhasil. Anda juga menulis __attr__deskripsi tetapi menggunakan __attrs__kode. Tidak ada yang bekerja untuk saya (werkzeug.datastructures.FileStorage)
Jonas