2008-09-20 26 views
78

Có phương pháp được xây dựng trong Python để có được một mảng của tất cả các biến cá thể của một lớp không? Ví dụ, nếu tôi có mã này:Làm cách nào để lấy các biến mẫu trong Python?

class hi: 
    def __init__(self): 
    self.ii = "foo" 
    self.kk = "bar" 

Có cách nào cho tôi để làm điều này:

>>> mystery_method(hi) 
["ii", "kk"] 

Edit: Tôi ban đầu đã yêu cầu cho các biến lớp sai lầm.

+0

dụ của bạn cho thấy "biến dụ". Biến lớp là một thứ khác. –

Trả lời

93

Mọi đối tượng đều có biến số __dict__ chứa tất cả các biến và giá trị của biến đó.

Hãy thử

>>> hi_obj = hi() 
>>> hi_obj.__dict__.keys() 
+7

FWIW, mô-đun kiểm tra cung cấp cho bạn một phương pháp đáng tin cậy hơn là dựa vào __dict__, mà không phải tất cả các trường hợp đều có. –

+1

Loại cá thể nào không có __dict__? Tôi chưa bao giờ gặp phải. –

+3

Một số kiểu tích hợp nhất định, chẳng hạn như int. Hãy thử nói "x = 5" và sau đó "x .__ dict__" và bạn sẽ nhận được AttributeError –

13

Bạn thường không thể nhận được trường hợp này thuộc tính được chỉ là một lớp, ít nhất là không phải không có instantiating lớp. Bạn có thể nhận được các thuộc tính instance cho một cá thể, hoặc các thuộc tính lớp cho một lớp. Xem mô-đun 'kiểm tra'. Bạn không thể có được một danh sách các thuộc tính instance vì các cá thể thực sự có thể có bất cứ thứ gì như thuộc tính, và - như trong ví dụ của bạn - cách bình thường để tạo chúng là chỉ gán cho chúng trong phương thức __init__.

Trường hợp ngoại lệ là nếu lớp của bạn sử dụng các vị trí, đây là danh sách các thuộc tính cố định mà lớp đó cho phép các trường hợp có. Các khe được giải thích trong http://www.python.org/2.2.3/descrintro.html, nhưng có nhiều cạm bẫy khác nhau với các khe; chúng ảnh hưởng đến bố cục bộ nhớ, vì vậy nhiều thừa kế có thể có vấn đề và thừa kế nói chung cũng phải tính đến các vị trí trong tài khoản.

+0

Downvoting vì "bạn không thể có được một danh sách các thuộc tính dụ" chỉ đơn giản là sai: cả hai vars() và __dict__ cho bạn chính xác điều đó. –

+2

Tôi cho rằng anh ta có nghĩa là "bạn không thể có danh sách tất cả các thuộc tính có thể có". Ví dụ, tôi thường sử dụng thế hệ lười và trình trang trí @property để thêm một biến cá thể vào lần đầu tiên nó được yêu cầu. Sử dụng __dict__ sẽ cho bạn biết về biến này một khi nó tồn tại nhưng không phải trước đó. –

+4

Tôi đã không downvote, và xin vui lòng nhận thấy những gì tôi thực sự nói: bạn không thể có được một danh sách các thuộc tính dụ * cho chỉ là một lớp *, đó là những gì mã đi kèm với câu hỏi cố gắng làm. –

9

Bạn cũng có thể kiểm tra nếu một đối tượng có một biến cụ thể với:

>>> hi_obj = hi() 
>>> hasattr(hi_obj, "some attribute") 
4

dụ của bạn cho thấy "biến dụ", không thực sự biến lớp.

Tìm trong hi_obj.__class__.__dict__.items() cho các biến lớp, cùng với các thành viên khác trong lớp như chức năng của thành viên và mô đun chứa.

class Hi(object): 
    class_var = (23, 'skidoo') # class variable 
    def __init__(self): 
     self.ii = "foo" # instance variable 
     self.jj = "bar" 

Biến lớp được chia sẻ bởi tất cả các phiên bản của lớp.

73

Sử dụng VAR()

class Foo(object): 
    def __init__(self): 
     self.a = 1 
     self.b = 2 

vars(Foo()) #==> {'a': 1, 'b': 2} 
vars(Foo()).keys() #==> ['a', 'b'] 
+6

+1 Cá nhân tôi nghĩ cú pháp này sạch hơn là sử dụng __dict__, vì các thuộc tính có dấu gạch dưới kép được cho là "riêng tư" trong cú pháp Python. –

+2

@Martin: '__method' là riêng tư,' __method__' là một phương pháp đặc biệt, không nhất thiết là riêng tư; Tôi muốn nói các phương pháp đặc biệt xác định capabilites của một đối tượng chứ không phải là phương pháp. – u0b34a0f6ae

+2

'__method__' khá xấu, và tôi nghĩ rằng họ đã được đặt tên theo cách đó để cố gắng và ngăn chặn mọi người tránh xa việc sử dụng chúng trừ khi thật cần thiết. Trong trường hợp này, chúng ta có các vars thay thế(). –

6

Suggest

>>> print vars.__doc__ 
vars([object]) -> dictionary 

Without arguments, equivalent to locals(). 
With an argument, equivalent to object.__dict__. 

Trong otherwords, về cơ bản nó chỉ kết thúc tốt đẹp __dict__

5

Mặc dù không trực tiếp một câu trả lời cho câu hỏi OP, có một khá ngọt ngào cách tìm ra những biến nào nằm trong phạm vi trong một hàm. hãy xem mã này:

>>> def f(x, y): 
    z = x**2 + y**2 
    sqrt_z = z**.5 
    return sqrt_z 

>>> f.func_code.co_varnames 
('x', 'y', 'z', 'sqrt_z') 
>>> 

Thuộc tính func_code có tất cả những thứ thú vị trong đó. Nó cho phép bạn làm một số thứ thú vị.Dưới đây là ví dụ về cách tôi đã sử dụng điều này:

def exec_command(self, cmd, msg, sig): 

    def message(msg): 
     a = self.link.process(self.link.recieved_message(msg)) 
     self.exec_command(*a) 

    def error(msg): 
     self.printer.printInfo(msg) 

    def set_usrlist(msg): 
     self.client.connected_users = msg 

    def chatmessage(msg): 
     self.printer.printInfo(msg) 

    if not locals().has_key(cmd): return 
    cmd = locals()[cmd] 

    try: 
     if 'sig' in cmd.func_code.co_varnames and \ 
         'msg' in cmd.func_code.co_varnames: 
      cmd(msg, sig) 
     elif 'msg' in cmd.func_code.co_varnames: 
      cmd(msg) 
     else: 
      cmd() 
    except Exception, e: 
     print '\n-----------ERROR-----------' 
     print 'error: ', e 
     print 'Error proccessing: ', cmd.__name__ 
     print 'Message: ', msg 
     print 'Sig: ', sig 
     print '-----------ERROR-----------\n' 
11

Cả hai phương thức Vars() và dict sẽ hoạt động cho ví dụ OP được đăng, nhưng chúng sẽ không hoạt động cho các đối tượng được xác định "lỏng" như:

class foo: 
    a = 'foo' 
    b = 'bar' 

Để in tất cả các thuộc tính không thể được gọi, bạn có thể sử dụng chức năng sau:

def printVars(object): 
    for i in [v for v in dir(object) if not callable(getattr(object,v))]: 
     print '\n%s:' % i 
     exec('print object.%s\n\n') % i 
+4

'exec ('đối tượng in.% S \ n \ n')% i' phải được viết là' print getattr (object, i) ' – user102008

Các vấn đề liên quan