Liệt kê các thuộc tính của một đối tượng


330

Có cách nào để lấy danh sách các thuộc tính tồn tại trong các thể hiện của một lớp không?

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

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

Kết quả mong muốn là "multi, str" sẽ là đầu ra. Tôi muốn điều này để xem các thuộc tính hiện tại từ các phần khác nhau của một tập lệnh.


75
Hầu như tất cả mọi người trong Python đều đặt tên cho các lớp của họ như thế nào NewClass. Bạn có thể bất chấp sự mong đợi của mọi người nếu bạn sử dụng quy ước đặt tên như thế nào new_class.
Mike Graham

Mặc dù nó tương tác với con người và không thể được sử dụng theo chương trình, help()chức năng giúp nhận thông tin về các lớp, hàm, nội trang, mô-đun và hơn thế nữa
ytpillai


Tại sao không có câu trả lời nào được đánh dấu là 'Được chấp nhận'?
pfabri

Câu trả lời:


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

Bạn cũng có thể tìm thấy pprint hữu ích.


29
Vấn đề sử dụng dict chỉ xuất hiện trên r / python. ai đó đã chỉ ra rằng vars (a) tương đương với .__ dict__
David

5
Trong trường hợp bất cứ ai thắc mắc, điều này cũng hoạt động trên Python 2.7
Ben Mordecai

8
Để được cụ thể, pprint.pprint(a.__dict__)một bản in đẹp trên các thuộc tính.
smci

1
Chắc chắn điều pprintđó KHÔNG hoạt động trên Python 2.6.
John Greene

3
Lưu ý rằng điều này chỉ hoạt động cho các lớp do người dùng định nghĩa, không dành cho các loại mở rộng hoặc mở rộng.
ivan_pozdeev

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

Sau đó, bạn có thể kiểm tra loại nào với type()hoặc nếu là một phương thức với callable().


dir hoạt động tốt hơn trên các lớp với thuộc tính get / set quá tải
ogurets 7/07/2016

dir (ví dụ) liệt kê rất nhiều điều mà bạn có thể không quan tâm
jciloa

Đây là chức năng duy nhất có cho tôi tất cả các thuộc tính có sẵn trên bostontập dữ liệu từ sklearn - __dict__trống, trong khi thực tế có 5 thuộc tính khả dụng
Coruscate5

72

vars(obj) trả về các thuộc tính của một đối tượng.


53

Tất cả các câu trả lời trước đều đúng, bạn có ba tùy chọn cho những gì bạn đang hỏi

  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)lợi nhuậnfoo.__dict__
Boris

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

Điều này tất nhiên sẽ in bất kỳ phương thức hoặc thuộc tính nào trong định nghĩa lớp. Bạn có thể loại trừ các phương thức "riêng tư" bằng cách thay đổi i.startwith('__')thànhi.startwith('_')


24

Các kiểm tra mô-đun cung cấp cách dễ dàng để kiểm tra một đối tượng:

Mô-đun kiểm tra cung cấp một số chức năng hữu ích để giúp nhận thông tin về các đối tượng sống như mô-đun, lớp, phương thức, hàm, tracebacks, đối tượng khung và đối tượng mã.


Sử dụng getmembers()bạn có thể thấy tất cả các thuộc tính của lớp của bạn, cùng với giá trị của chúng. Để loại trừ các thuộc tính riêng tư hoặc được bảo vệ sử dụng .startswith('_'). Để loại trừ các phương thức hoặc hàm sử dụng inspect.ismethod()hoặc 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)

Lưu ý rằng ismethod()được sử dụng trên phần tử thứ hai ivì đầu tiên chỉ đơn giản là một chuỗi (tên của nó).

Offtopic: Sử dụng CamelCase cho tên lớp.


13

Bạn có thể sử dụng dir(your_object)để có được các thuộc tính và getattr(your_object, your_object_attr)để có được các giá trị

sử dụng :

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

Điều này đặc biệt hữu ích nếu đối tượng của bạn không có __dict__. Nếu đó không phải là trường hợp bạn cũng có thể thử var (your_object)


11

Nó thường được đề cập rằng để liệt kê một danh sách đầy đủ các thuộc tính bạn nên sử dụng dir(). Tuy nhiên, lưu ý rằng trái với niềm tin phổ biến dir()không đưa ra tất cả các thuộc tính. Ví dụ, bạn có thể nhận thấy rằng __name__có thể bị thiếu trong dir()danh sách của một lớp mặc dù bạn có thể truy cập nó từ chính lớp đó. Từ tài liệu trên dir()( Python 2 , Python 3 ):

Vì dir () được cung cấp chủ yếu để thuận tiện cho việc sử dụng tại dấu nhắc tương tác, nên nó cố gắng cung cấp một tập hợp tên thú vị hơn là cố gắng cung cấp một tập hợp tên được xác định chặt chẽ hoặc nhất quán và hành vi chi tiết của nó có thể thay đổi trong các bản phát hành. Ví dụ, các thuộc tính siêu dữ liệu không có trong danh sách kết quả khi đối số là một lớp.

Một hàm như sau có xu hướng hoàn thiện hơn, mặc dù không có gì đảm bảo tính đầy đủ vì danh sách được trả về dir()có thể bị ảnh hưởng bởi nhiều yếu tố bao gồm thực hiện __dir__()phương thức, hoặc tùy chỉnh __getattr__()hoặc __getattribute__()trên lớp hoặc một trong các cha mẹ của nó. Xem các liên kết được cung cấp để biết thêm chi tiết.

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

9

Bạn muốn cái này để làm gì? Có thể khó có được câu trả lời tốt nhất cho bạn mà không biết ý định chính xác của bạn.

  • Hầu như luôn luôn tốt hơn để làm điều này bằng tay nếu bạn muốn hiển thị một thể hiện của lớp của bạn theo một cách cụ thể. Điều này sẽ bao gồm chính xác những gì bạn muốn và không bao gồm những gì bạn không muốn, và thứ tự sẽ được dự đoán.

    Nếu bạn đang tìm cách để hiển thị nội dung của một lớp, hãy định dạng thủ công các thuộc tính bạn quan tâm và cung cấp đây là phương thức __str__hoặc __repr__cho lớp của bạn.

  • Nếu bạn muốn tìm hiểu về những phương thức và những thứ như vậy tồn tại cho một đối tượng để hiểu cách thức hoạt động của nó, hãy sử dụng help. help(a)sẽ cho bạn thấy một đầu ra được định dạng về lớp của đối tượng dựa trên các tài liệu của nó.

  • dirtồn tại để lập trình nhận tất cả các thuộc tính của một đối tượng. (Truy cập __dict__làm một cái gì đó tôi sẽ nhóm như nhau nhưng tôi sẽ không sử dụng bản thân mình.) Tuy nhiên, điều này có thể không bao gồm những thứ bạn muốn và nó có thể bao gồm những thứ bạn không muốn. Nó không đáng tin cậy và mọi người nghĩ rằng họ muốn nó thường xuyên hơn nhiều so với họ.

  • Trên một ghi chú hơi trực giao, có rất ít hỗ trợ cho Python 3 tại thời điểm hiện tại. Nếu bạn quan tâm đến việc viết phần mềm thực sự, bạn sẽ muốn các công cụ của bên thứ ba như numpy, lxml, Twisted, PIL hoặc bất kỳ số lượng khung web nào chưa hỗ trợ Python 3 và không sớm có kế hoạch. Sự khác biệt giữa 2,6 và nhánh 3.x là nhỏ, nhưng sự khác biệt trong hỗ trợ thư viện là rất lớn.


4
Tôi chỉ muốn chỉ ra rằng năm năm sau (bây giờ), tôi tin rằng tất cả các mô-đun bên thứ ba mà bạn đề cập đến hỗ trợ python3. Nguồn: python3wos.appspot.com
pzkpfw

8

Có nhiều hơn một cách để làm điều đó:

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

Khi chạy, mã này tạo ra:

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
Tại sao câu trả lời này đã bị hạ cấp? Đối với mục đích gỡ lỗi, dir hoạt động khá tốt!
Dunatotatos

Khá hoạt động với Python 2.7.x. Chính xác những gì tôi muốn.
Davidson Lima

7

Vui lòng xem tập lệnh shell python đã được thực hiện theo trình tự, ở đây bạn sẽ nhận được các thuộc tính của một lớp ở định dạng chuỗi được phân tách bằng dấu phẩy.

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

Tôi đang sử dụng python 3,4


Và nếu bạn muốn chỉ có danh sách có thể sử dụng chỉ a.__dict__.keys(). Tuy nhiên nếu bạn muốn biết nếu một đối tượng có thuộc tính cụ thể bạn có thể sử dụng hasattr.
berna1111

4

Ngoài những câu trả lời này, tôi sẽ bao gồm một hàm (python 3) để phun ra gần như toàn bộ cấu trúc của bất kỳ giá trị nào. Nó sử dụng dirđể thiết lập danh sách đầy đủ các tên thuộc tính, sau đó sử dụng getattrvới mỗi tên. Nó hiển thị loại của mọi thành viên của giá trị và khi có thể cũng hiển thị toàn bộ thành viên:

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

Bây giờ bất kỳ điều nào sau đây sẽ cung cấp cái nhìn sâu sắc:

get_info(None)
get_info('hello')

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

Wow, đó là một viên ngọc quý!
pfabri

Vâng, đây là một cứu cánh. không thể hiểu tại sao điều này tôi không thể dễ dàng giải nén các danh sách này và chắc chắn loại đủ có thuộc tính " vị trí " thuộc loại "tuple" Đây là giá trị của vị trí : ["nsname", "hostmaster", "serial", "refresh", "thử lại", "hết hạn", "minttl", "ttl"]
Mik R

3

Nhận các thuộc tính của một đối tượng

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)

Đầu ra

['__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

Như được viết trước khi sử dụng obj.__dict__có thể xử lý các trường hợp phổ biến nhưng một số lớp không có __dict__thuộc tính và sử dụng __slots__(chủ yếu là cho hiệu quả bộ nhớ).

ví dụ cho một cách kiên cường hơn để làm điều này:

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

đầu ra của mã này:

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

Lưu ý1:
Python là một ngôn ngữ động và luôn biết rõ hơn về các lớp bạn đang cố gắng lấy các thuộc tính vì ngay cả mã này cũng có thể bỏ lỡ một số trường hợp.

Lưu ý2:
mã này chỉ xuất ra các biến thể hiện có nghĩa là các biến lớp không được cung cấp. ví dụ:

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

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

mã đầu ra:

{'path': '/questions'}

Mã này không in urlthuộc tính lớp và có thể bỏ qua các thuộc tính lớp mong muốn.
Đôi khi chúng ta có thể nghĩ rằng một thuộc tính là một thành viên thể hiện nhưng nó không và sẽ không được hiển thị bằng ví dụ này.


2
Một lớp có thể có __dict__ __slots__ , vì vậy bạn có thể muốn thử cả hai thay vì chỉ đọc chính tả.
cz

1
  • Sử dụng __dict__hoặc vars không hoạt động vì nó bỏ lỡ __slots__.
  • Sử dụng __dict____slots__ không hoạt động vì nó bỏ lỡ __slots__từ các lớp cơ sở.
  • Việc sử dụng dir không hoạt động vì nó bao gồm các thuộc tính lớp, chẳng hạn như các phương thức hoặc thuộc tính, cũng như các thuộc tính đối tượng.
  • Sử dụng varstương đương với việc sử dụng __dict__.

Đây là thứ tốt nhất tôi có:

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

Chúng ta hãy áp dụng hàm này cho lớp đơn giản: lớp C: def __init __ (self): print ("created") i = 42 Tại sao mã của bạn đưa ra danh sách trống cho lớp đó? (Ý tôi là nếu o = C () sau đó get_attrs (o) là trống) Nó cũng đã làm cho get_attrs ( "mystr")
GED

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

Nó không hoạt động với các tên thuộc tính lớp bắt đầu bằng chữ in hoa hoặc dấu gạch dưới đơn.
fviktor

0

Vui lòng xem trình tự thực thi kịch bản shell Python sau đây, nó sẽ đưa ra giải pháp từ việc tạo lớp đến trích xuất tên trường của các thể hiện.

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

Chúng tôi cũng có thể kiểm tra khả năng gọi của từng thuộc
tính.visit

-4

__attr__ đưa ra danh sách các thuộc tính của một thể hiện.

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

Không phải lúc nào cũng làm việc. Ngoài ra, bạn viết __attr__trong mô tả nhưng sử dụng __attrs__trong mã. Không làm việc cho tôi (werkzeug.datastructures.FileStorage)
Jonas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.