วิธีรับรายการทั้งหมดของวิธีการและคุณลักษณะของวัตถุ?


230
dir(re.compile(pattern)) 

ไม่ส่งคืนรูปแบบเป็นหนึ่งในองค์ประกอบของรายการ มันคือผลตอบแทน:

['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn']

ตามคู่มือมันควรจะมี

ชื่อแอตทริบิวต์ของวัตถุชื่อของแอตทริบิวต์ของคลาสและเรียกซ้ำของแอตทริบิวต์ของคลาสพื้นฐานของคลาสนั้น

มันก็บอกว่า

รายการไม่จำเป็นต้องสมบูรณ์

มีวิธีที่จะได้รับที่สมบูรณ์รายการ? ฉันมักจะสันนิษฐานว่า dir ส่งคืนรายการทั้งหมด แต่ดูเหมือนจะไม่ ...

นอกจากนี้ยังมีวิธีการแสดงรายการคุณลักษณะเท่านั้นหรือไม่ หรือวิธีการเท่านั้น?

แก้ไข: นี่เป็นข้อผิดพลาดในหลาม -> ตามที่คาดคะเนว่าได้รับการแก้ไขในสาขา 3.0 (และอาจเป็น 2.6)


5
การใช้งานdir()หรือโมดูลตรวจสอบเป็นวิธีที่เหมาะสมในการทำเช่นนั้น คุณใช้reโมดูลเป็นตัวอย่างหรือคุณต้องการบรรลุเป้าหมายพิเศษหรือไม่?

1
คุณแน่ใจหรือว่ารูปแบบนั้นถูกเก็บเป็นข้อมูลเมื่อรวบรวมไว้จริง ๆ ? ฉันอยู่ภายใต้การแสดงผลที่จุดของการรวบรวมรูปแบบคือการผลิตออโต้ จำกัด แน่นอนที่จำเป็นในการแยกรูปแบบที่กำหนด
Kyle Strand

@hop ไม่สามารถ dir ถูก sidestepped โดยชั้นเรียน? ตัวอย่างเช่นพวกเขาสามารถทำของพวกเขาใน__dir__()
ytpillai

ytpillai: ถูกต้อง แต่ใน Python 3 เท่านั้นดังนั้นคำถามคือว่าคลาสดังกล่าวจะตกอยู่ภายใต้ "กรณีทั่วไป" หรือไม่

คำตอบ:


140

สำหรับสมบูรณ์รายการแอตทริบิวต์คำตอบสั้น ๆ คือไม่มี ปัญหาคือมีการกำหนดแอตทริบิวต์จริง ๆ เป็นอาร์กิวเมนต์ที่ยอมรับโดยgetattrฟังก์ชันในตัว ในขณะที่ผู้ใช้สามารถนำไปใช้งาน__getattr__ใหม่ได้ทันใดนั้นก็อนุญาตให้แอททริบิวต์ทุกชนิดไม่มีวิธีที่เป็นไปได้ทั่วไปในการสร้างรายการนั้น dirฟังก์ชันส่งกลับกุญแจใน__dict__แอตทริบิวต์คือทั้งหมดที่สามารถเข้าถึงคุณลักษณะถ้า__getattr__วิธีการไม่ได้ reimplemented

สำหรับคำถามที่สองมันไม่สมเหตุสมผลเลย จริงๆแล้วเมธอดคือคุณสมบัติที่เรียกได้ว่าไม่มีอะไรมาก คุณสามารถกรองแอ็ตทริบิวต์ที่เรียกได้และใช้inspectโมดูลเพื่อกำหนดวิธีการเรียนวิธีการหรือฟังก์ชั่น


1
inpect.getmembers (re.compile (รูปแบบ)) ไม่ได้ให้รูปแบบการเป็นสมาชิกดังนั้นอาจใช้ dir ภายใน ... นี่มันแย่มาก!
Bartosz Radaczyński

ฉันสามารถใช้ callable เพื่อตรวจสอบว่าเป็นวิธีการหรือไม่ แต่นั่นไม่ใช่ประเด็น ... ประเด็นคือฉันไม่สามารถเชื่อใจ dir ที่จะส่งคืนแม้กระทั่งรายการคุณลักษณะที่เปิดเผยต่อสาธารณะได้จริง ๆ ...
Bartosz Radaczyński

2
การตรวจสอบนั้นหมายถึงว่า "อย่างน้อยที่สุด" น่าเชื่อถือเหมือน dir () ในทางกลับกันโมดูลนั้นซับซ้อนมาก

สิ่งใดที่คุณกำหนดโดย "เปิดเผยต่อสาธารณะ" หากคุณหมายถึง "สามารถเข้าถึงได้" หมายความว่าสาเหตุที่หายไปด้วยเหตุผลที่ให้ไว้ มิฉะนั้น 'dir' จะส่งคืนรายการของคุณสมบัติที่สามารถเข้าถึงได้ด้วยการใช้งานเริ่มต้นของ getattr เสมอ
PierreBdR

2
dir (my_class) ส่งคืนบางสิ่งที่แตกต่างจาก my_class .__ dict __. keys () อดีตยังแสดงผลลัพธ์ของคลาสเช่นinitและdoc
JuanPi

58

นั่นคือเหตุผลที่เพิ่ม__dir__()วิธีการใหม่ใน python 2.6

ดู:


ฉันได้รับข้อผิดพลาดนี้: >> dir __ (pyrenderdoc) การติดตามกลับ (การโทรล่าสุดครั้งล่าสุด): ไฟล์ "<string>", บรรทัดที่ 1 ใน <โมดูล> NameError: ชื่อ '__dir ' ไม่ได้กำหนดไว้
Mona Jalal

__dir__ () เป็นวิธีการในวัตถุไม่ใช่ฟังก์ชั่น - โปรดอ่านลิงก์ในคำตอบและสิ่งนี้
Moe

หนึ่งซับเพื่อพิมพ์แอ็ตทริบิวต์และค่าทั้งหมด:pprint({k:getattr(ojb,k) for k in obj.__dir__()})
Czechnology

21

ต่อไปนี้เป็นคำตอบของ PierreBdR และ Moe ที่ใช้งานได้จริง:

  • สำหรับงูหลาม> = 2.6 และแบบใหม่เรียน , dir()น่าจะเป็นพอ
  • สำหรับคลาสแบบเก่าอย่างน้อยเราสามารถทำสิ่งที่โมดูลมาตรฐานทำเพื่อสนับสนุนการทำให้แท็บสมบูรณ์: นอกเหนือจากdir()นั้นค้นหา__class__และจากนั้นไปที่__bases__:

    # code borrowed from the rlcompleter module
    # tested under Python 2.6 ( sys.version = '2.6.5 (r265:79063, Apr 16 2010, 13:09:56) \n[GCC 4.4.3]' )
    
    # or: from rlcompleter import get_class_members
    def get_class_members(klass):
        ret = dir(klass)
        if hasattr(klass,'__bases__'):
            for base in klass.__bases__:
                ret = ret + get_class_members(base)
        return ret
    
    
    def uniq( seq ): 
        """ the 'set()' way ( use dict when there's no set ) """
        return list(set(seq))
    
    
    def get_object_attrs( obj ):
        # code borrowed from the rlcompleter module ( see the code for Completer::attr_matches() )
        ret = dir( obj )
        ## if "__builtins__" in ret:
        ##    ret.remove("__builtins__")
    
        if hasattr( obj, '__class__'):
            ret.append('__class__')
            ret.extend( get_class_members(obj.__class__) )
    
            ret = uniq( ret )
    
        return ret

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


9

เพื่อเสริมเท่านั้น:

  1. dir()เป็นเครื่องมือที่ทรงพลังที่สุด / พื้นฐาน ( แนะนำมากที่สุด )
  2. โซลูชั่นอื่น ๆ ที่ไม่ใช่dir()แค่ให้ทางของพวกเขาในการจัดการการส่งออกของdir()

    การแสดงรายการแอตทริบิวต์ระดับที่ 2 หรือไม่เป็นสิ่งสำคัญที่จะทำการกลั่นกรองด้วยตัวเองเพราะบางครั้งคุณอาจต้องการกรอง vars ภายในด้วยการขีดเส้นใต้ชั้นนำ__แต่บางครั้งคุณอาจต้องการ__doc__doc-string

  3. __dir__()และdir()ส่งคืนเนื้อหาที่เหมือนกัน
  4. __dict__และdir()มีความแตกต่าง __dict__ส่งคืนเนื้อหาที่ไม่สมบูรณ์
  5. สำคัญ : __dir__()บางครั้งสามารถเขียนทับด้วยฟังก์ชั่นค่าหรือประเภทโดยผู้เขียนเพื่อวัตถุประสงค์ใด ๆ

    นี่คือตัวอย่าง:

    \\...\\torchfun.py in traverse(self, mod, search_attributes)
    445             if prefix in traversed_mod_names:
    446                 continue
    447             names = dir(m)
    448             for name in names:
    449                 obj = getattr(m,name)

    TypeError: บ่ง__dir__ของ'object'วัตถุที่ต้องการโต้แย้ง

    ผู้เขียน PyTorch ปรับเปลี่ยน__dir__()วิธีการเป็นสิ่งที่ต้องมีการโต้แย้ง การปรับเปลี่ยนนี้ทำให้dir()ล้มเหลว

  6. หากคุณต้องการรูปแบบที่เชื่อถือได้ในการสำรวจคุณลักษณะทั้งหมดของวัตถุโปรดจำไว้ว่าทุกมาตรฐาน pythonic สามารถถูกแทนที่และอาจไม่ถือและทุกการประชุมอาจไม่น่าเชื่อถือ


5

นี่คือวิธีที่ฉันทำมันมีประโยชน์สำหรับวัตถุที่กำหนดเองง่าย ๆ ที่คุณเพิ่มคุณสมบัติ:

รับวัตถุที่สร้างขึ้นด้วยobj = type("Obj",(object,),{})หรือเพียงแค่:

class Obj: pass
obj = Obj()

เพิ่มคุณสมบัติบางอย่าง:

obj.name = 'gary'
obj.age = 32

จากนั้นเพื่อรับพจนานุกรมที่มีเฉพาะแอตทริบิวต์ที่กำหนดเอง:

{key: value for key, value in obj.__dict__.items() if not key.startswith("__")}

# {'name': 'gary', 'age': 32}

รายการแอตทริบิวต์ทั้งหมดใน Python 3.x: {key: value สำหรับ key, ค่าใน obj .__ dict __. items () ถ้าไม่ใช่ key.startswith ("__")} ['_
declar_fields
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.