Làm thế nào để có được một danh sách đầy đủ các phương thức và thuộc tính của đối tượng?


230
dir(re.compile(pattern)) 

không trả về mẫu là một trong các thành phần của danh sách. Cụ thể là nó trả về:

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

Theo hướng dẫn, nó được cho là chứa

Tên thuộc tính của đối tượng, tên thuộc tính của lớp và đệ quy các thuộc tính của lớp cơ sở của lớp.

Nó cũng nói rằng

Danh sách này không nhất thiết phải đầy đủ.

Có cách nào để có được danh sách đầy đủ? Tôi luôn cho rằng dir trả về một danh sách đầy đủ nhưng dường như nó không ...

Ngoài ra: có cách nào để liệt kê chỉ các thuộc tính? Hay chỉ có phương pháp?

Chỉnh sửa: đây thực sự là một lỗi trong python -> được cho là nó đã được sửa trong nhánh 3.0 (và có lẽ trong 2.6)


5
sử dụng dir()hoặc mô-đun kiểm tra nói chung là cách đúng đắn để làm điều đó. Bạn đã sử dụng remô-đun như một ví dụ hay bạn muốn đạt được một mục tiêu đặc biệt?

1
Bạn có chắc chắn rằng mẫu thực sự được lưu giữ dưới dạng dữ liệu sau khi được biên dịch không? Tôi có ấn tượng rằng điểm biên dịch một mẫu là tạo ra automata trạng thái hữu hạn cần thiết để phân tích mẫu đã cho.
Kyle Strand

@hop không thể dir được sidestepped bởi các lớp? Ví dụ: họ có thể thực hiện trên__dir__()
ytpillai

ytpillai: đúng, nhưng chỉ trong Python 3. Mặc dù vậy, câu hỏi đặt ra là liệu một lớp như vậy có thuộc "trường hợp chung" hay không

Câu trả lời:


140

Đối với danh sách đầy đủ các thuộc tính, câu trả lời ngắn gọn là: không. Vấn đề là các thuộc tính thực sự được định nghĩa là các đối số được hàm tích hợp chấp nhận getattr. Khi người dùng có thể thực hiện lại __getattr__, đột nhiên cho phép bất kỳ loại thuộc tính nào, không có cách chung nào có thể để tạo danh sách đó. Các dirchức năng trả về các phím trong __dict__thuộc tính, tức là tất cả các thuộc tính truy cập được nếu các __getattr__phương pháp không được thực hiện lại.

Đối với câu hỏi thứ hai, nó không thực sự có ý nghĩa. Trên thực tế, các phương thức là thuộc tính có thể gọi được, không có gì hơn. Mặc dù bạn có thể lọc các thuộc tính có thể gọi được và sử dụng inspectmô đun xác định các phương thức, phương thức hoặc hàm của lớp.


1
inpect.getmembers (re.compile (mẫu)) cũng không mang lại mô hình như một thành viên, vì vậy nó có thể sử dụng dir trong nội bộ ... Điều này thật tệ!
Bartosz Radaczyński

Tôi cũng có thể sử dụng có thể gọi được để kiểm tra xem chúng có phải là phương thức hay không, nhưng đó không phải là vấn đề ... Vấn đề là tôi không thể tin tưởng dir sẽ trả về ngay cả danh sách các thuộc tính thực sự hiển thị công khai ...
Bartosz Radaczyński

2
kiểm tra có nghĩa là "ít nhất là" đáng tin cậy như dir (). mặt khác, lại là một mô-đun rất phức tạp

Bạn định nghĩa gì bởi "hiển thị công khai"? Nếu bạn có nghĩa là "có thể được truy cập", thì đó là một nguyên nhân bị mất vì lý do được đưa ra. Mặt khác, 'dir' luôn trả về danh sách các thuộc tính có thể truy cập được với cài đặt getattr mặc định.
PierreBdR

2
dir (my_group) trả về một cái gì đó khác với my_group .__ dict __. Keys (). trước đây cũng đưa ra các phương thức của lớp như initdoc
JuanPi

58

Đó là lý do tại sao __dir__()phương thức mới đã được thêm vào python 2.6

xem:


Tôi gặp lỗi này: >> dir __ (pyrenderdoc) TracBack (cuộc gọi gần đây nhất vừa qua): Tệp "<chuỗi>", dòng 1, trong <module> NameError: tên '__dir ' không được xác định
Mona Jalal

__dir__ () là một phương thức trên đối tượng, không phải là hàm - vui lòng đọc các liên kết trong câu trả lời và điều này
Moe

Một lớp lót để in tất cả các thuộc tính và giá trị của chúng:pprint({k:getattr(ojb,k) for k in obj.__dir__()})
Công nghệ

21

Đây là một bổ sung thực tế cho câu trả lời của PierreBdR và Moe:

  • Đối với Python> = 2.6 và các lớp kiểu mới , dir()dường như là đủ.
  • Đối với các lớp kiểu cũ , ít nhất chúng ta có thể làm những gì một mô-đun chuẩn làm để hỗ trợ hoàn thành tab: ngoài việc dir()tìm kiếm __class__, và sau đó đi tìm __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
    

(Mã kiểm tra và đầu ra bị xóa để đơn giản, nhưng về cơ bản đối với các đối tượng kiểu mới, chúng ta dường như có kết quả tương tự get_object_attrs()như đối với dir()các lớp kiểu cũ, phần bổ sung chính cho dir()đầu ra dường như là __class__thuộc tính.)


9

Chỉ để bổ sung:

  1. dir()nhất mạnh mẽ / công cụ cơ bản. (Được khuyến nghị nhất )
  2. Các giải pháp khác hơn dir()là chỉ cung cấp cách thức xử lý đầu ra của họdir() .

    Liệt kê các thuộc tính cấp 2 hoặc không, điều quan trọng là bạn tự thực hiện việc sàng lọc, bởi vì đôi khi bạn có thể muốn sàng lọc các vars nội bộ với các dấu gạch dưới hàng đầu __, nhưng đôi khi bạn cũng có thể cần __doc__chuỗi doc.

  3. __dir__()dir()trả về nội dung giống hệt nhau.
  4. __dict__dir()là khác nhau. __dict__trả về nội dung không đầy đủ.
  5. QUAN TRỌNG : __dir__()đôi khi có thể được ghi đè bằng một chức năng, giá trị hoặc loại, bởi tác giả cho bất kỳ mục đích nào.

    Đây là một ví dụ:

    \\...\\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: mô tả __dir__của 'object'đối tượng cần một đối số

    Tác giả của PyTorch đã sửa đổi __dir__()phương thức thành một cái gì đó đòi hỏi một đối số. Sửa đổi này làm cho dir()thất bại.

  6. Nếu bạn muốn một sơ đồ đáng tin cậy để vượt qua tất cả các thuộc tính của một đối tượng, hãy nhớ rằng mọi tiêu chuẩn pythonic có thể bị ghi đè và có thể không được giữ , và mọi quy ước có thể không đáng tin cậy.


5

Đây là cách tôi thực hiện, hữu ích cho các đối tượng tùy chỉnh đơn giản mà bạn tiếp tục thêm thuộc tính:

Đưa ra một đối tượng được tạo bằng obj = type("Obj",(object,),{})hoặc đơn giản là:

class Obj: pass
obj = Obj()

Thêm một số thuộc tính:

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

sau đó, để có được một từ điển chỉ với các thuộc tính tùy chỉnh:

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

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

danh sách tất cả các thuộc tính trong Python 3.x: {. chính: giá trị cho khóa, giá trị trong obj .__ dict __ mục () nếu không key.startswith ( "__")} [ '_ declared_fields'] phím ().
above_c_level
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.