lặp qua tất cả các biến thành viên của một lớp trong python


91

Làm cách nào để bạn có được danh sách tất cả các biến trong một lớp có thể lặp lại? Giống như người dân địa phương (), nhưng cho một lớp học

class Example(object):
    bool143 = True
    bool2 = True
    blah = False
    foo = True
    foobar2000 = False

    def as_list(self)
       ret = []
       for field in XXX:
           if getattr(self, field):
               ret.append(field)
       return ",".join(ret)

cái này sẽ trở lại

>>> e = Example()
>>> e.as_list()
bool143, bool2, foo

Tại sao không thể sử dụng sử dụng for field in [ self.bool143, self.bool2, self.blah, self.foo, self.foobar2000 ]? Làm thế nào nó xảy ra khi bạn không biết các biến cá thể của lớp?
S.Lott

4
S.Lott: Đó là những gì tôi đã kết thúc. Trong mã thực của tôi, tôi có 40 biến, và tôi nghĩ sẽ tốt hơn và KHÔ hơn khi không phải tạo danh sách lặp lại theo cách thủ công.
Priestc 10/09/09

Câu trả lời:


151
dir(obj)

cung cấp cho bạn tất cả các thuộc tính của đối tượng. Bạn cần tự lọc ra các thành viên từ các phương pháp, v.v.:

class Example(object):
    bool143 = True
    bool2 = True
    blah = False
    foo = True
    foobar2000 = False

example = Example()
members = [attr for attr in dir(example) if not callable(getattr(example, attr)) and not attr.startswith("__")]
print members   

Sẽ cung cấp cho bạn:

['blah', 'bool143', 'bool2', 'foo', 'foobar2000']

9
tại sao thuyết minh một đối tượng: dir (Ví dụ ()) thay vì chỉ các kiểu lớp dir (Ví dụ)
Erdal

8
và làm thế nào để bạn nhận được các giá trị?
knutole

7
@knutole: getattr (object, attr)
opello

8
Làm thế nào để callable(attr)hoạt động? Không phải là attrmột chuỗi?
cubuspl42,

6
bạn nên đã sử dụng vars(Example).items()hoặc vars(instance.__class__).items()thay vì dir()nếu bạn muốn kiểm tra xem nó có thể được gọi hay không vì dir sẽ chỉ trả lại ' strings như tên ..
rrw

117

Nếu bạn chỉ muốn các biến (không có hàm), hãy sử dụng:

vars(your_object)

5
Bạn vẫn cần phải lọc vars nhưng đây là câu trả lời đúng
gaborous

3
thực sự thích cách tiếp cận này sẽ sử dụng nó để tìm ra những gì cần nối tiếp trước khi gửi các trạng thái qua mạng chẳng hạn ...
Thom

7
varskhông không bao gồm các biến lớp, chỉ có các biến ví dụ.
DilithiumMatrix

2
@DilithiumMatrix bạn cần sử dụng vars (THECLASSITSELF) trên chính lớp đó để nhận các biến lớp. Kiểm tra câu trả lời của tôi bên dưới.
AmirHossein

2
Sử dụng phương thức này để trả lời cụ thể câu hỏi của OP: members = list(vars(example).keys())as (ít nhất là trong python3) varstrả về dictánh xạ tên của biến thành viên với giá trị của nó.
Michael Hall

28

@truppo: câu trả lời của bạn gần như đúng, nhưng có thể gọi sẽ luôn trả về sai vì bạn chỉ chuyển vào một chuỗi. Bạn cần những thứ như sau:

[attr for attr in dir(obj()) if not callable(getattr(obj(),attr)) and not attr.startswith("__")]

cái nào sẽ lọc ra các chức năng


6
>>> a = Example()
>>> dir(a)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', 'bool143', 'bool2', 'blah',
'foo', 'foobar2000', 'as_list']

—Như bạn thấy, điều đó cung cấp cho bạn tất cả các thuộc tính, vì vậy bạn sẽ phải lọc ra một chút. Nhưng về cơ bản, đó dir()là những gì bạn đang tìm kiếm.


-1
row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns} if r else {}

Dùng cái này.


Gây hiểu lầm. Không có thuộc tính ' bảng ' trong các lớp theo mặc định.
ben26941

-2
    class Employee:
    '''
    This class creates class employee with three attributes 
    and one function or method
    '''

    def __init__(self, first, last, salary):
        self.first = first
        self.last = last
        self.salary = salary

    def fullname(self):
        fullname=self.first + ' ' + self.last
        return fullname

emp1 = Employee('Abhijeet', 'Pandey', 20000)
emp2 = Employee('John', 'Smith', 50000)

print('To get attributes of an instance', set(dir(emp1))-set(dir(Employee))) # you can now loop over

-3

Cách dễ dàng để làm điều này là lưu tất cả các phiên bản của lớp trong a list.

a = Example()
b = Example()
all_examples = [ a, b ]

Các vật thể không xuất hiện một cách tự nhiên. Một số phần trong chương trình của bạn đã tạo ra chúng vì một lý do. Việc tạo ra được thực hiện vì một lý do. Việc thu thập chúng trong một danh sách cũng có thể được thực hiện vì một lý do.

Nếu bạn sử dụng một nhà máy, bạn có thể làm điều này.

class ExampleFactory( object ):
    def __init__( self ):
        self.all_examples= []
    def __call__( self, *args, **kw ):
        e = Example( *args, **kw )
        self.all_examples.append( e )
        return e
    def all( self ):
        return all_examples

makeExample= ExampleFactory()
a = makeExample()
b = makeExample()
for i in makeExample.all():
    print i

Tôi thích ý tưởng đó (tôi thực sự có thể sử dụng nó trong một dự án hiện tại). Tuy nhiên, đây không phải là câu trả lời cho câu hỏi: OP muốn liệt kê các thuộc tính, không phải bản thân các cá thể.
balpha 09/09/09

@balpha: Rất tiếc. Không đọc câu hỏi. 90% trường hợp là bản sao của "làm cách nào để tìm tất cả các bản sao của một lớp." Câu hỏi thực tế (bây giờ bạn đã chỉ ra) không hợp lý. Bạn biết các biến cá thể, chỉ cần tạo một danh sách.
S.Lott
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.