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.ImplementationName
wł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']
>>>
attributes
zamiast 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
stasis
jest statyczny, dyno
dynamiczny (por. dekorator właściwości) i classy
jest atrybutem klasy. Jeśli po prostu to zrobimy, __dict__
albo vars
dostaniemy 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}
type
Wywoł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 predicate
argument, 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).