IC # robimy to poprzez refleksję. W Javascript jest to proste:
for(var propertyName in objectName)
var currentPropertyValue = objectName[propertyName];
Jak to zrobić w Pythonie?
IC # robimy to poprzez refleksję. W Javascript jest to proste:
for(var propertyName in objectName)
var currentPropertyValue = objectName[propertyName];
Jak to zrobić w Pythonie?
@property.
Odpowiedzi:
for property, value in vars(theObject).items():
print(property, ":", value)
Należy pamiętać, że w rzadkich przypadkach istnieje __slots__właściwość, której takie klasy często nie mają __dict__.
__setattr__(). Ustawienie wartości bezpośrednio w słowniku pomija metodę ustawiającą obiektu (i / lub jego rodziców). W Pythonie dość często zdarza się, że więcej rzeczy niż na pierwszy rzut oka dzieje się w tle podczas ustawiania atrybutów (np. Higieny), używanie setattr()zapewnia, że nie przegapisz lub jesteś zmuszony do samodzielnego obsługiwania ich.
vars()zwraca tylko statyczne składowe (tj. atrybuty obiektów i metody zarejestrowane z tymi obiektami __dict__). To nie nie powrócić dynamiczne członków (tj atrybuty obiektów i metod dynamicznie zdefiniowane przez ten obiekt w __getattr__()metodzie lub podobnej magii). Najprawdopodobniej pożądana file.ImplementationNamewłaściwość jest definiowana dynamicznie i dlatego nie jest dostępna dla vars()ani dir().
Zobacz inspect.getmembers(object[, predicate]).
Zwraca wszystkich członków obiektu na liście par (nazwa, wartość) posortowanych według nazwy. Jeśli podano opcjonalny argument predykatu, uwzględniane są tylko elementy członkowskie, dla których predykat zwraca wartość true.
>>> [name for name,thing in inspect.getmembers([])]
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
'__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__',
'__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__','__reduce_ex__',
'__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__',
'__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index',
'insert', 'pop', 'remove', 'reverse', 'sort']
>>>
attributeszamiast members(czy jest jakaś różnica między nimi?). Mogli poprawić nazwę w Pythonie 3.0, aby była spójna.
__dict__, przepraszam.
inspect.getmembers()otacza dir()(przeważnie pomijalne) korzyści uboczne (A), w tym dynamiczne atrybuty klas i atrybuty metaklasy oraz (B) wykluczenie elementów członkowskich nie pasujących do przekazanego predykatu. Ziewać, prawda? inspect.getmembers()jest odpowiedni dla bibliotek innych firm, które ogólnie obsługują wszystkie możliwe typy obiektów. Jednak w przypadku standardowych zastosowań jest to dir()absolutnie wystarczające.
dir()to prosty sposób. Spójrz tutaj:
dir()dziękuję.
__dict__Właściwość obiektu jest słownikiem wszystkich innych określonych właściwościach. Zauważ, że klasy Pythona mogą przesłonić getattr
i sprawić, że rzeczy wyglądają jak właściwości, ale ich nie ma __dict__. Jest również wbudowane funkcje vars()i dir()które są różne w subtelny sposób. I __slots__może zastąpić __dict__w niektórych nietypowych klasach.
Obiekty są skomplikowane w Pythonie. __dict__to właściwe miejsce do rozpoczęcia programowania w stylu refleksji. dir()to miejsce, od którego możesz zacząć, jeśli hakujesz w interaktywnej powłoce.
print vars.__doc__wskazuje, że With an argument, equivalent to object.__dict__Więc jakie byłyby subtelne różnice?
dla statków jednoliniowych:
print vars(theObject)
Jeśli szukasz odzwierciedlenia wszystkich właściwości, powyższe odpowiedzi są świetne.
Jeśli po prostu szukasz kluczy ze słownika (który różni się od „obiektu” w Pythonie), użyj
my_dict.keys()
my_dict = {'abc': {}, 'def': 12, 'ghi': 'string' }
my_dict.keys()
> ['abc', 'def', 'ghi']
obj['key']porównaniu z obj.property) i pytanie dotyczyło właściwości obiektów. Umieściłem tutaj swoją odpowiedź, ponieważ między nimi jest łatwo.
Jest to całkowicie objęte innymi odpowiedziami, ale wyjaśnię to wyraźnie. Obiekt może mieć atrybuty klas oraz statyczne i dynamiczne atrybuty instancji.
class foo:
classy = 1
@property
def dyno(self):
return 1
def __init__(self):
self.stasis = 2
def fx(self):
return 3
stasisjest statyczny, dynodynamiczny (por. dekorator właściwości) i classyjest atrybutem klasy. Jeśli po prostu to zrobimy, __dict__albo varsdostaniemy tylko statyczny.
o = foo()
print(o.__dict__) #{'stasis': 2}
print(vars(o)) #{'stasis': 2}
Więc jeśli chcemy, inni __dict__dostaną wszystko (i więcej). Obejmuje to magiczne metody i atrybuty oraz normalne metody związane. Unikajmy więc tych:
d = {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}
print(d) #{'stasis': 2, 'classy': 1, 'dyno': 1}
typeWywołana z własności urządzone metody (atrybut dynamiczny) daje typ zwracanej wartości, nie method. Aby to udowodnić, json stringify it:
import json
print(json.dumps(d)) #{"stasis": 2, "classy": 1, "dyno": 1}
Gdyby to była metoda, zawaliłaby się.
TL; DR. spróbuj wezwać extravar = lambda o: {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}wszystkie trzy, ale nie metody ani magię.
Myślę, że warto pokazać różnicę między różnymi wymienionymi opcjami - często obraz jest wart tysiąca słów.
>>> from pprint import pprint
>>> import inspect
>>>
>>> class a():
x = 1 # static class member
def __init__(self):
self.y = 2 # static instance member
@property
def dyn_prop(self): # dynamic property
print('DYNPROP WAS HERE')
return 3
def test(self): # function member
pass
@classmethod
def myclassmethod(cls): # class method; static methods behave the same
pass
>>> i = a()
>>> pprint(i.__dict__)
{'y': 2}
>>> pprint(vars(i))
{'y': 2}
>>> pprint(dir(i))
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'dyn_prop',
'myclassmethod',
'test',
'x',
'y']
>>> pprint(inspect.getmembers(i))
DYNPROP WAS HERE
[('__class__', <class '__main__.a'>),
('__delattr__',
<method-wrapper '__delattr__' of a object at 0x000001CB891BC7F0>),
('__dict__', {'y': 2}),
('__dir__', <built-in method __dir__ of a object at 0x000001CB891BC7F0>),
('__doc__', None),
('__eq__', <method-wrapper '__eq__' of a object at 0x000001CB891BC7F0>),
('__format__', <built-in method __format__ of a object at 0x000001CB891BC7F0>),
('__ge__', <method-wrapper '__ge__' of a object at 0x000001CB891BC7F0>),
('__getattribute__',
<method-wrapper '__getattribute__' of a object at 0x000001CB891BC7F0>),
('__gt__', <method-wrapper '__gt__' of a object at 0x000001CB891BC7F0>),
('__hash__', <method-wrapper '__hash__' of a object at 0x000001CB891BC7F0>),
('__init__',
<bound method a.__init__ of <__main__.a object at 0x000001CB891BC7F0>>),
('__init_subclass__',
<built-in method __init_subclass__ of type object at 0x000001CB87CA6A70>),
('__le__', <method-wrapper '__le__' of a object at 0x000001CB891BC7F0>),
('__lt__', <method-wrapper '__lt__' of a object at 0x000001CB891BC7F0>),
('__module__', '__main__'),
('__ne__', <method-wrapper '__ne__' of a object at 0x000001CB891BC7F0>),
('__new__', <built-in method __new__ of type object at 0x00007FFCA630AB50>),
('__reduce__', <built-in method __reduce__ of a object at 0x000001CB891BC7F0>),
('__reduce_ex__',
<built-in method __reduce_ex__ of a object at 0x000001CB891BC7F0>),
('__repr__', <method-wrapper '__repr__' of a object at 0x000001CB891BC7F0>),
('__setattr__',
<method-wrapper '__setattr__' of a object at 0x000001CB891BC7F0>),
('__sizeof__', <built-in method __sizeof__ of a object at 0x000001CB891BC7F0>),
('__str__', <method-wrapper '__str__' of a object at 0x000001CB891BC7F0>),
('__subclasshook__',
<built-in method __subclasshook__ of type object at 0x000001CB87CA6A70>),
('__weakref__', None),
('dyn_prop', 3),
('myclassmethod', <bound method a.myclassmethod of <class '__main__.a'>>),
('test', <bound method a.test of <__main__.a object at 0x000001CB891BC7F0>>),
('x', 1),
('y', 2)]
Podsumowując:
vars()i __dict__zwracają tylko właściwości lokalne instancji;dir()zwraca wszystko, ale tylko jako listę nazw członków łańcucha; właściwości dynamiczne nie są wywoływane;inspect.getmembers()zwraca wszystko jako listę krotek (name, value); faktycznie uruchamia właściwości dynamiczne i przyjmuje opcjonalny predicateargument, który może odfiltrować elementy członkowskie według wartości .Tak więc moje zdroworozsądkowe podejście polega zwykle na używaniu dir()w wierszu poleceń iw getmembers()programach, chyba że mają zastosowanie szczególne względy wydajności.
Zauważ, że aby zachować czystość, nie uwzględniłem __slots__- jeśli był obecny, został wyraźnie umieszczony w celu odpytywania i powinien być używany bezpośrednio. Nie opisałem też metaklas, które mogą być trochę owłosione (większość ludzi i tak nigdy ich nie użyje).