รายการคุณสมบัติของวัตถุ


330

มีวิธีการรับรายการคุณลักษณะที่มีอยู่ในอินสแตนซ์ของคลาสหรือไม่

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

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

ผลลัพธ์ที่ต้องการคือ "multi, str" จะถูกส่งออก ฉันต้องการสิ่งนี้เพื่อดูคุณสมบัติปัจจุบันจากส่วนต่าง ๆ ของสคริปต์


75
NewClassแทบทุกคนในชื่อหลามชั้นเรียนของพวกเขาเช่น new_classคุณอาจจะท้าทายความคาดหวังของผู้คนถ้าคุณใช้การประชุมตั้งชื่อเช่น
Mike Graham

แม้ว่ามันจะเป็นแบบมนุษย์และไม่สามารถใช้โปรแกรมได้ แต่help()ฟังก์ชันช่วยในการรับข้อมูลเกี่ยวกับคลาสฟังก์ชั่น
บิวด์อิน

1

ทำไมไม่มีคำตอบที่ทำเครื่องหมายว่า 'ยอมรับ'?
pfabri

คำตอบ:


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

นอกจากนี้คุณยังอาจพบว่าpprint มีประโยชน์


29
ปัญหาการใช้dictแสดงขึ้นที่ r / python บางคนชี้ให้เห็นว่า vars (a) เทียบเท่ากับ. __ dict__
David

5
ในกรณีที่ใครสงสัยก็สามารถใช้งาน Python 2.7 ได้เช่นกัน
Ben Mordecai

8
หากต้องการเจาะจงpprint.pprint(a.__dict__)ให้พิมพ์สวยบนแอตทริบิวต์
smci

1
แน่นอนว่าpprintใช้ไม่ได้กับ Python 2.6
John Greene

3
โปรดทราบว่าสิ่งนี้ใช้ได้เฉพาะกับคลาสที่ผู้ใช้กำหนดเท่านั้นไม่ใช่สำหรับประเภทบิวท์อินหรือส่วนขยาย
ivan_pozdeev

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

จากนั้นคุณสามารถทดสอบสิ่งที่ประเภทอยู่กับหรือถ้าเป็นวิธีการที่มีtype()callable()


dir ทำงานได้ดีขึ้นในคลาสที่มีแอททริบิวต์ที่โอเวอร์โหลดรับ / ตั้ง
59

dir (อินสแตนซ์) แสดงรายการสิ่งต่าง ๆ มากมายที่คุณอาจไม่สนใจ
jciloa

นี่เป็นฟังก์ชั่นเดียวที่ทำให้ฉันมีแอตทริบิวต์ทั้งหมดที่มีอยู่ในbostonชุดข้อมูลจาก sklearn - __dict__ว่างเปล่าเมื่อจริง ๆ แล้วมี 5 คุณลักษณะที่พร้อมใช้งาน
Coruscate5


53

คำตอบก่อนหน้าทั้งหมดถูกต้องคุณมีสามตัวเลือกสำหรับสิ่งที่คุณถาม

  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)ผลตอบแทนfoo.__dict__
Boris

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

หลักสูตรนี้จะพิมพ์วิธีการหรือคุณลักษณะใด ๆ ในการกำหนดชั้นเรียน คุณสามารถยกเว้นวิธี "ส่วนตัว" ได้โดยเปลี่ยนi.startwith('__')เป็นi.startwith('_')


24

ตรวจสอบโมดูลมีวิธีการที่ง่ายต่อการตรวจสอบวัตถุ:

โมดูลตรวจสอบมีฟังก์ชันที่มีประโยชน์หลายอย่างเพื่อช่วยรับข้อมูลเกี่ยวกับวัตถุสดเช่นโมดูลคลาสวิธีการฟังก์ชันการติดตามย้อนกลับวัตถุเฟรมและวัตถุรหัส


การใช้getmembers()คุณสามารถดูคุณลักษณะทั้งหมดในชั้นเรียนของคุณพร้อมกับค่าของพวกเขา .startswith('_')หากต้องการยกเว้นคุณลักษณะส่วนตัวหรือการป้องกันการใช้งาน วิธีการในการยกเว้นหรือฟังก์ชั่นการใช้งานหรือinspect.ismethod()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)

โปรดทราบว่าismethod()จะใช้ในองค์ประกอบที่สองของiตั้งแต่แรกเป็นเพียงสตริง (ชื่อ)

Offtopic: ใช้CamelCaseสำหรับชื่อคลาส


13

คุณสามารถใช้dir(your_object)เพื่อรับคุณลักษณะและgetattr(your_object, your_object_attr)รับค่า

การใช้งาน:

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

สิ่งนี้มีประโยชน์อย่างยิ่งหากวัตถุของคุณไม่มี __dict__ หากไม่ใช่กรณีนี้คุณสามารถลองใช้ var (your_object) ได้เช่นกัน


11

dir()ก็มักจะบอกว่าไปที่รายการรายการที่สมบูรณ์ของคุณลักษณะที่คุณควรใช้ อย่างไรก็ตามโปรดทราบว่าการขัดกับความเชื่อที่ได้รับความนิยมdir()นั้นไม่ได้นำคุณลักษณะทั้งหมดออกมา ตัวอย่างเช่นคุณอาจสังเกตเห็นว่า__name__อาจหายไปจากdir()รายชื่อของชั้นแม้ว่าคุณสามารถเข้าถึงได้จากชั้นเรียนเอง จากเอกสารในdir()( Python 2 , Python 3 ):

เนื่องจาก dir () ได้รับการจัดหาเป็นหลักเพื่อความสะดวกในการใช้งานที่พร้อมต์แบบโต้ตอบมันจึงพยายามให้ชื่อชุดที่น่าสนใจมากกว่าที่จะพยายามให้ชื่อชุดที่กำหนดไว้อย่างเข้มงวดหรือสม่ำเสมอและพฤติกรรมรายละเอียดอาจเปลี่ยนแปลงไปตามรุ่น ตัวอย่างเช่นแอตทริบิวต์ metaclass ไม่ได้อยู่ในรายการผลลัพธ์เมื่ออาร์กิวเมนต์เป็นคลาส

ฟังก์ชันดังต่อไปนี้มีแนวโน้มที่จะสมบูรณ์มากขึ้นแม้ว่าจะไม่รับประกันความสมบูรณ์เนื่องจากรายการที่ส่งคืนโดยdir()อาจได้รับผลกระทบจากหลายปัจจัยรวมถึงการใช้__dir__()วิธีการหรือการปรับแต่ง__getattr__()หรือ__getattribute__()ในชั้นเรียนหรือหนึ่งในผู้ปกครอง ดูลิงก์ที่ให้ไว้สำหรับรายละเอียดเพิ่มเติม

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

9

คุณต้องการสิ่งนี้เพื่ออะไร อาจเป็นเรื่องยากที่คุณจะได้รับคำตอบที่ดีที่สุดโดยไม่ทราบเจตนาที่แท้จริงของคุณ

  • จะเป็นการดีกว่าถ้าคุณต้องการแสดงอินสแตนซ์ของคลาสของคุณในแบบเฉพาะเจาะจง ซึ่งจะรวมถึงสิ่งที่คุณต้องการและไม่รวมสิ่งที่คุณไม่ต้องการและคำสั่งซื้อจะสามารถคาดเดาได้

    หากคุณกำลังมองหาวิธีที่จะแสดงเนื้อหาของชั้นเรียนให้จัดรูปแบบคุณสมบัติที่คุณสนใจด้วยตนเองและระบุสิ่งนี้เป็นวิธีการ__str__หรือ__repr__ชั้นเรียนของคุณ

  • หากคุณต้องการที่จะเรียนรู้เกี่ยวกับสิ่งที่มีอยู่และวิธีการดังกล่าวสำหรับวัตถุที่จะเข้าใจวิธีการทำงาน, helpการใช้งาน help(a)จะแสดงผลลัพธ์ที่จัดรูปแบบเกี่ยวกับคลาสของวัตถุตามเอกสารของมัน

  • dirมีอยู่สำหรับการรับคุณลักษณะทั้งหมดของวัตถุโดยทางโปรแกรม (การเข้าถึง__dict__ทำสิ่งที่ฉันจะจัดกลุ่มเหมือนกัน แต่ฉันจะไม่ใช้ตัวเอง) อย่างไรก็ตามสิ่งนี้อาจไม่รวมสิ่งที่คุณต้องการและอาจรวมถึงสิ่งที่คุณไม่ต้องการ มันไม่น่าเชื่อถือและผู้คนคิดว่าพวกเขาต้องการมันบ่อยกว่าที่พวกเขาทำ

  • ในโน้ตแบบมุมฉากมีการสนับสนุนน้อยมากสำหรับ Python 3 ในเวลาปัจจุบัน หากคุณมีความสนใจในการเขียนซอฟต์แวร์จริงคุณจะต้องการสิ่งที่เป็นของบุคคลที่สามเช่น numpy, lxml, Twisted, PIL หรือกรอบงานเว็บจำนวนเท่าใดก็ได้ที่ยังไม่รองรับ Python 3 และไม่ได้วางแผนที่จะเร็วเกินไป ความแตกต่างระหว่าง 2.6 และสาขา 3.x มีขนาดเล็ก แต่ความแตกต่างในการสนับสนุนห้องสมุดมีขนาดใหญ่มาก


4
ฉันแค่จะชี้ให้เห็นว่าห้าปีต่อมา (ตอนนี้) ฉันเชื่อว่าโมดูลของบุคคลที่สามทั้งหมดที่คุณพูดถึงรองรับ python3 ที่มา: python3wos.appspot.com
pzkpfw

8

มีมากกว่าหนึ่งวิธีที่จะทำ:

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

เมื่อเรียกใช้รหัสนี้จะสร้าง:

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
ทำไมคำตอบนี้จึงถูกลดระดับลง? สำหรับวัตถุประสงค์ในการดีบั๊ก dir ใช้งานได้ดี!
Dunatotatos

ทำงานได้ดีกับ Python 2.7.x สิ่งที่ฉันต้องการ
Davidson ลิมา

7

โปรดดูสคริปต์เปลือกงูหลามซึ่งถูกดำเนินการตามลำดับที่นี่คุณจะได้รับคุณลักษณะของคลาสในรูปแบบสตริงคั่นด้วยเครื่องหมายจุลภาค

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

ฉันใช้ python 3.4


และถ้าคุณต้องการเฉพาะรายการเท่านั้นที่สามารถa.__dict__.keys()ใช้ได้ อย่างไรก็ตามหากคุณต้องการทราบว่าวัตถุมีคุณสมบัติเฉพาะที่คุณสามารถใช้ได้หรือhasattrไม่
berna1111

4

นอกจากคำตอบเหล่านี้ฉันจะรวมฟังก์ชั่น (python 3) สำหรับพ่นโครงสร้างทั้งหมดของมูลค่าใด ๆ มันใช้dirเพื่อสร้างรายการชื่อทรัพย์สินทั้งหมดจากนั้นใช้getattrกับแต่ละชื่อ มันแสดงประเภทของสมาชิกทุกคนของค่าและเมื่อเป็นไปได้ยังแสดงสมาชิกทั้งหมด:

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

ตอนนี้ข้อใดข้อหนึ่งต่อไปนี้ควรทำความเข้าใจ:

get_info(None)
get_info('hello')

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

ว้าวนั่นเป็นอัญมณี!
pfabri

ใช่นี่เป็นผู้ช่วยชีวิต ไม่ทราบสาเหตุที่ฉันไม่สามารถแกะรายการเหล่านี้ได้อย่างง่ายดายและประเภทที่แน่นอนมีคุณสมบัติ " ช่อง " ของประเภท "tuple" นี่คือค่าช่อง : ["nsname", "hostmaster", "serial", "refresh", "ลองใหม่", "หมดอายุ", "minttl", "ttl"]
Mik R

3

รับคุณลักษณะของวัตถุ

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)

เอาท์พุต

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

ตามที่เขียนไว้ก่อนการใช้obj.__dict__สามารถจัดการกรณีทั่วไป แต่บางคลาสไม่มี__dict__คุณสมบัติและการใช้งาน__slots__ (ส่วนใหญ่ให้มีประสิทธิภาพหน่วยความจำ)

ตัวอย่างสำหรับวิธีที่ยืดหยุ่นในการทำเช่นนี้:

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

ผลลัพธ์ของรหัสนี้:

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

Note1:
Python เป็นภาษาแบบไดนามิกและจะเป็นการดีกว่าที่จะทราบคลาสที่คุณพยายามรับแอททริบิวต์เนื่องจากรหัสนี้อาจพลาดบางกรณี

Note2:
โค้ดนี้ให้ผลลัพธ์เฉพาะตัวแปรอินสแตนซ์เท่านั้นซึ่งหมายความว่าไม่ได้ระบุตัวแปรคลาส ตัวอย่างเช่น:

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

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

รหัสออก:

{'path': '/questions'}

รหัสนี้ไม่ได้พิมพ์urlแอตทริบิวต์ class และอาจละเว้นคุณลักษณะระดับที่ต้องการ
บางครั้งเราอาจคิดว่าแอตทริบิวต์เป็นสมาชิกอินสแตนซ์ แต่มันไม่ได้และจะไม่แสดงโดยใช้ตัวอย่างนี้


2
ชั้นเรียนสามารถมี__dict__ และ __slots__ดังนั้นคุณอาจต้องการลองทั้งสองอย่างมากกว่าแค่พจน์
cz

1
  • การใช้__dict__หรือvars ไม่ทำงานเพราะพลาดไป__slots__เพราะมันคิดถึงออก
  • การใช้__dict__และ__slots__ ไม่ทำงานเพราะพลาดไป__slots__จากคลาสพื้นฐาน
  • การใช้dir งานไม่ได้เพราะมันมีคุณสมบัติคลาสเช่นวิธีการหรือคุณสมบัติเช่นเดียวกับคุณลักษณะของวัตถุ
  • ใช้เทียบเท่ากับการใช้vars__dict__

นี่คือสิ่งที่ดีที่สุดที่ฉันมี:

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

ลองใช้ฟังก์ชั่นนี้กับคลาสง่ายๆ spome: class C: def __init __ (ตัวเอง): print ("created") i = 42 ทำไมรหัสของคุณถึงให้รายการว่างสำหรับคลาสนั้น? (ผมหมายถึงถ้า o = C () แล้ว get_attrs (O) เป็นที่ว่างเปล่า) นอกจากนี้ยังได้สำหรับ get_attrs ( "mystr")
ged

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

มันไม่ทำงานกับชื่อแอตทริบิวต์คลาสเริ่มต้นด้วยอักษรตัวใหญ่หรือขีดล่างเดียว
fviktor

0

โปรดดูการดำเนินการสคริปต์เชลล์ Python ต่อไปนี้ตามลำดับซึ่งจะให้โซลูชันจากการสร้างคลาสเพื่อแยกชื่อฟิลด์ของอินสแตนซ์

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

นอกจากนี้เรายังสามารถตรวจสอบ callablilty ของแต่ละคุณลักษณะเยี่ยมชมstackoverflow.com/questions/1398022/ …
hygull

-4

__attr__ ให้รายการคุณลักษณะของอินสแตนซ์

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

ไม่ได้ผลเสมอไป นอกจากนี้คุณเขียน__attr__คำอธิบาย แต่ใช้__attrs__ในรหัส ไม่ทำงานสำหรับฉัน (werkzeug.datastructures.FileStorage)
Jonas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.