2013-06-12 30 views
6

Tôi muốn gọi một phương pháp để cho tôi một mệnh lệnh của tất cả các "không riêng tư" (tôi sử dụng thuật ngữ "riêng tư" hơi lỏng lẻo ở đây vì nó không thực sự tồn tại trong Python) và các thuộc tính không được xây dựng (tức là những thứ không bắt đầu bằng dấu gạch dưới đơn hoặc kép) trên một lớp. Một cái gì đó giống như vars (MyClass) sẽ chỉ trả về các thuộc tính "công khai" trên lớp đó.Có phương pháp Python nào để truy cập tất cả các thuộc tính không phải là riêng tư và không được xây dựng của một lớp không?

Tôi biết rằng

from M import * 

không nhập khẩu đối tượng có tên bắt đầu bằng dấu gạch dưới. (http://www.python.org/dev/peps/pep-0008/#id25) Cách nhập thực hiện? Thông qua chức năng dựng sẵn hoặc chỉ bằng cách kiểm tra dấu gạch dưới? Cách pythonic để làm điều này là gì?

Ví dụ:

class MyClass(object): 
    def __init__(self): 
     do_stuff() 
    def _private(self): 
     print 'private' 
    def __gets_name_mangled(self: 
     print 'becomes _MyClass__gets_name_mangled()' 
    def public(self): 
     print 'public' 

Nếu tôi làm

vars(MyClass).keys() 

tôi nhận được

['_MyClass__gets_name_mangled', '__module__', '_private', '__doc__', '__dict__', '__weakref__', 'public', '__init__'] 

Làm thế nào tôi có thể nhận được chỉ

['public'] 

Hay tôi chỉ cần tự mình kiểm tra dấu gạch dưới? Nó chỉ có vẻ như sẽ có một cách nhiệt tình để làm điều này.

Để biết thêm về dấu gạch dưới và dấu gạch đôi, xem: What is the meaning of a single- and a double-underscore before an object name?

+1

'vars (MyClass) .keys() 'là' dir (MyClass)' – Elazar

+6

Tôi không biết về bất kỳ chức năng thực hiện điều này. Luôn luôn có: '[f cho f trong dir (MyClass) nếu không f.startswith ('_')]' – Blender

+3

@Elazar nếu hiểu biết của tôi là đúng, dir (MyClass) sẽ trả về các thuộc tính của các lớp được phân lớp bởi MyClass (nếu MyClass đã xảy ra với phân lớp một cái gì đó) ngoài những người được xác định bên trong MyClass, trong khi vars (MyClass) chỉ trả về những thuộc tính được xác định bên trong MyClass. Sự khác biệt tinh tế. Nhưng câu hỏi ban đầu là viết tắt. – andy

Trả lời

4

Trên thực tế, nó sẽ là unpythonic cho chức năng như vậy để tồn tại - bởi vì "chính thức" không có lĩnh vực private hay protected/tài sản bằng Python.

Mặc dù việc loại bỏ các thuộc tính mô-đun bằng dấu gạch dưới hàng đầu (thường là một số chi tiết triển khai) trong import * từ một số mô đun *, nó không hữu ích trong ngữ cảnh của bất kỳ đối tượng nào khác.

Vì vậy, nếu bạn chỉ cần liệt kê các phương thức/thuộc tính "công khai" của một đối tượng, chỉ cần lặp qua kết quả của dir và thả tên với dấu gạch dưới hàng đầu.


* "trong import * từ một số mô-đun"

Thông thường nó không phải là thực hành tốt nhất. Xem xét ví dụ sau:

mô-đun Aa1a2 định nghĩa

mô-đun Bb1b2 định nghĩa

Mã này trong mô-đun C làm việc như mong đợi:

from A import a1, a2 
from B import * 

Hãy tưởng tượng chúng ta thêm chức năng a1 trong mô-đun B. Bây giờ đột nhiên mô-đun C bị hỏng, mặc dù chúng tôi đã không chạm vào nó.

+0

hết mức tò mò: thực hiện nhập * chỉ cần kiểm tra dấu gạch dưới hàng đầu giống như cách @Blender đề xuất tôi làm điều đó? – andy

+0

+1 - Chỉ là những gì tôi nghĩ. – Elazar

+0

bạn có thể làm rõ quan điểm của mình về "không phải là phương pháp hay nhất" không? – andy

1

Tôi đang sử dụng chức năng này:

def print_all_public_fields(obj): 
    print(obj) 
    for a in dir(obj): 
     if not a.startswith('_') and not a.isupper(): 
      print('\t%s = %s' % (a, getattr(obj, a))) 

Tôi biết nó không phải là chính xác những gì bạn muốn, nhưng có lẽ nó sẽ cung cấp cho bạn một số ý tưởng.

2

Với sự hiểu biết dict lọc vars()

{ k:v for k,v in vars(myObject).items() if not k.startswith('_') } 

chuyển vào một hàm trả về một danh sách các thuộc tính mà không phải là 'mềm tin' hoặc callables. Bạn có thể trả về giá trị nếu bạn thích bằng cách thay đổi để dict hiểu như trên

def list_public_attributes(input_var): 
    return [k for k, v in vars(input_var).items() if 
      not (k.startswith('_') or callable(v))] 
Các vấn đề liên quan