Niedawno znalazłem się pisania kodu jak poniżej:Iterate nad obiektem za „publiczne” atrybuty
for name in dir(object): if name.startswith('__') : continue ...
Czy istnieje bardziej pythonic sposobem dostępu do przestrzeni nazw obiektu „publiczne”?
Niedawno znalazłem się pisania kodu jak poniżej:Iterate nad obiektem za „publiczne” atrybuty
for name in dir(object): if name.startswith('__') : continue ...
Czy istnieje bardziej pythonic sposobem dostępu do przestrzeni nazw obiektu „publiczne”?
Można przygotować listę „publiczne” atrybutów (jak liście lub jako generator) przed:
>>> public_props = (name for name in dir(object) if not name.startswith('_'))
>>> for name in public_props:
print name
Ale proszę przeczytać notatkę o dir()
funkcję w dokumentacji:
Note Because
dir()
is supplied primarily as a convenience for use at an interactive prompt, it tries to supply an interesting set of names more than it tries to supply a rigorously or consistently defined set of names, and its detailed behavior may change across releases. For example, metaclass attributes are not in the result list when the argument is a class.
Powinieneś należy także pamiętać, że każda klasa może implementować metodę __dir__()
, która może zwrócić listę nazw, które niekoniecznie odpowiadają nazwom atrybutów. Innymi słowy, dir(something)
nie gwarantuje, że wynik zwróci atrybuty something
.
Czy istnieje powód, aby preferować 'dir (object)' do 'object .__ dict__'? – Dave
obiekt .__ dict__ niekoniecznie zwraca atrybuty, które chcesz, przynajmniej z moich wyników testu, tak jest. –
Zamiast tego można użyć vars
function.
Na przykład:
>>> class C(object):
... def __init__(self):
... self.__foo = 'foo'
...
>>> c = C()
>>> dir(c)
['_C__foo', '__class__', '__delattr__', '__dict__', '__doc__', '__format__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__']
>>> vars(c)
{'_C__foo': 'foo'}
zauważyć, że jak Niklas R wskazał, zmienne z pojedynczym podkreślenia są również traktowane jako prywatne. Jednak funkcja vars()
ma tę zaletę, że eliminuje wszystkie oprócz zmiennych instancji.
Otrzymuję argument TypeError: vars() musi mieć atrybut __dict__' przy próbie tego na innych obiektach. – wim
Tak, funkcja 'vars()' może być używana tylko dla obiektów, które mają '__dict__'. Na przykład, jeśli na twojej klasie zdefiniowano '__slots__', nie będziesz mógł użyć funkcji' vars() '. – srgerg
Zauważ, że nie dostaniesz niczego, co jest własnością, więc nie tylko rzeczy z '__slots__' nie będą działały. –
Czuję Iterowanie nad listą zrozumienie jest nieco bardziej pythonic niż przy użyciu słowa kluczowego continue
, ale może to być po prostu kwestia gustu. To prawda, że nie jest o wiele bardziej elegancka niż to, co już masz.
for attr in (a for a in dir(object) if not a.startswith('_')):
pass
Uwaga: pojedyncze podkreślenia atrybuty nie są też "publiczne".
jaki problem rozwiązujesz w pierwszej kolejności, że ten konstrukt jest przydatny? – SingleNegationElimination
Co z 'dla nazwy w filtrze (lambda x: nie x.startswith ('_'), dir (obj)):'? Należy zauważyć, że w Pythonie nawet jedno podkreślenie ('_') ma na celu wskazanie *" prywatnego "atrybutu *. –
@NiklasR 'dla nazwy (x dla x w dir (obj), jeśli nie x.startswith ('_')):' nie potrzebuje filtra –