2013-06-12 21 views
6

Chciałbym nazwać metodę, aby dać mi dyktować wszystkie "nieprywatne" (używam tu terminu "prywatny" nieco luźniej, ponieważ tak naprawdę nie istnieje w Pythonie) i atrybutów niewbudowanych (np. te, które nie zaczynają się od pojedynczego lub podwójnego podkreślenia) w klasie. Coś jak vars (MyClass), które zwróci tylko "publiczne" atrybuty tej klasy.Czy istnieje metoda Pythona do uzyskiwania dostępu do wszystkich nieprywatnych i niewbudowanych atrybutów klasy?

Jestem świadomy, że

from M import * 

nie importuje obiekty, których nazwa zaczyna się od znaku podkreślenia. (http://www.python.org/dev/peps/pep-0008/#id25) Jak importuje to? Poprzez wbudowaną funkcję lub po prostu zaznaczając podkreślenia? Jaki jest pythonic sposób to zrobić?

Przykład:

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' 

Jeśli robię

vars(MyClass).keys() 

uzyskać

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

Jak mogę uzyskać tylko

['public'] 

Czy muszę sam sprawdzić podkreślenia? Wydaje się, że byłby to pythonic sposób na zrobienie tego.

Więcej informacji na temat podkreślenia i podwójne podkreślenia, patrz: What is the meaning of a single- and a double-underscore before an object name?

+1

'Vars (myClass) .keys()' 'jest dir (MyClass)' – Elazar

+6

nie wiem jakiejkolwiek funkcji, która to robi. Zawsze jest: '[f for f in dir (MyClass) jeśli nie f.startswith ('_')]' – Blender

+3

@Elazar jeśli moje zrozumienie jest poprawne, dir (MyClass) zwróci atrybuty klas, które są podklasy przez MyClass (jeśli MyClass zdarzyło się podklasy coś) oprócz tych zdefiniowanych w MyClass, podczas gdy vars (MyClass) zwraca tylko te atrybuty zdefiniowane w MyClass. Subtelna różnica. Ale oryginalne pytanie stoi. – andy

Odpowiedz

4

Właściwie byłoby unpythonic dla takiej funkcji do istnieje - ponieważ „oficjalnie” nie ma prywatne lub chronione Pola/właściwości w Pythonie.

Podczas gdy sensowne jest wyrzucanie atrybutów modułów z wiodącymi podkreśleniami (które są zwykle niektórymi szczegółami implementacji) podczas import * z jakiegoś modułu *, nie jest to użyteczne w kontekście żadnego innego obiektu.

Tak więc, jeśli chcesz wyświetlić tylko "publiczne" metody/atrybuty obiektu, po prostu wykonaj iterację z wynikiem dir i upuść nazwy z wiodącymi podkreśleniami.


* "podczas import * od jakiegoś modułu '"

Zwykle to nie jest najlepsza praktyka. Rozważmy kolejny przykład:

moduł A ma a1 i a2 zdefiniowane

moduł B ma b1 i b2 zdefiniowane

Ten kod w module C działa zgodnie z oczekiwaniami:

from A import a1, a2 
from B import * 

Wyobraź dodamy funkcja a1 w module B. Teraz nagle moduł C jest zepsuty, chociaż go nie dotknęliśmy.

+0

z ciekawości: czy import * wystarczy poszukać wiodących podkreśleń w taki sam sposób, jak @Blender zasugerował, że to robię? – andy

+0

+1 - Dokładnie to, co myślałem. – Elazar

+0

czy możesz wyjaśnić swój punkt widzenia na temat "nie najlepszej praktyki"? – andy

1

używam tej funkcji:

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))) 

wiem, że to nie jest dokładnie to, co chcesz, ale być może będzie to daje pewne wyobrażenie.

2

Z pojmowania dict, który filtruje vars()

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

Przeniesiony do funkcji, która zwraca listę atrybutów, które nie są „miękkie prywatny” lub callables. Można powrócić wartości, jeśli lubisz zmieniając do dict zrozumieniem jak wyżej

def list_public_attributes(input_var): 
    return [k for k, v in vars(input_var).items() if 
      not (k.startswith('_') or callable(v))] 
Powiązane problemy