Mam obiekt Pythona z kilkoma atrybutami i metodami. Chcę iterować po atrybutach obiektów.
class my_python_obj(object):
attr1='a'
attr2='b'
attr3='c'
def method1(self, etc, etc):
#Statements
Chcę wygenerować słownik zawierający wszystkie atrybuty obiektów i ich bieżące wartości, ale chcę to zrobić w sposób dynamiczny (więc jeśli później dodam kolejny atrybut, nie muszę również pamiętać o aktualizacji mojej funkcji).
W php zmienne mogą być używane jako klucze, ale obiekty w Pythonie nie są obsługiwane i jeśli używam do tego notacji z kropką, tworzy nowy atrybut o nazwie moja var, co nie jest moim zamiarem.
Żeby było jaśniej:
def to_dict(self):
'''this is what I already have'''
d={}
d["attr1"]= self.attr1
d["attr2"]= self.attr2
d["attr3"]= self.attr3
return d
·
def to_dict(self):
'''this is what I want to do'''
d={}
for v in my_python_obj.attributes:
d[v] = self.v
return d
Aktualizacja: Przez atrybuty mam na myśli tylko zmienne tego obiektu, a nie metody.
python
oop
attributes
iteration
Pablo Mescher
źródło
źródło
predicate
argumentu, aby przekazać wywoływalną funkcję, która odfiltrowałaby (ograniczyłaby?) funkcje (która pozbyłaby się metod).Odpowiedzi:
Zakładając, że masz klasę taką jak
wywołanie
dir
obiektu zwraca wszystkie atrybuty tego obiektu, w tym specjalne atrybuty Pythona. Chociaż niektóre atrybuty obiektów są wywoływalne, takie jak metody.Możesz zawsze odfiltrować specjalne metody, używając rozumienia listy.
lub jeśli wolisz mapy / filtry.
Jeśli chcesz odfiltrować metody, możesz użyć wbudowanego
callable
jako sprawdzenia.Możesz również sprawdzić różnicę między twoją klasą a jej obiektem instancji przy użyciu.
źródło
callable
lubtypes.MethodType
. Co się stanie, jeśli dodam atrybut o nazwie „_foo”, który przechowuje jakiś wynik pośredni lub wewnętrzną strukturę danych? Co się stanie, jeśli po prostu nieszkodliwie dodam atrybut do klasyname
, powiedzmy a, a teraz nagle zostanie on uwzględniony._foo
iname
ponieważ są one teraz atrybutami obiektu. Jeśli nie chcesz ich uwzględniać, możesz wykluczyć je z warunku rozumienia listy. Powyższy kod jest popularnym idiomem Pythona i popularnym sposobem introspekcji obiektów Pythona.dir()
"kłamie" tylko wtedy, gdy przeszedł metaklasy (skrajny przypadek krawędzi) lub klasy z atrybutami ozdobionymi przez@DynamicClassAttribute
(kolejny skrajny przypadek skrajny). W obu przypadkach wywołaniedirs()
opakowaniainspect.getmembers()
rozwiązuje ten problem. Jednak w przypadku obiektów standardowych absolutnie wystarczające jest podejście oparte na zrozumieniu list w tym rozwiązaniu, odfiltrowując elementy niewymienialne . To, że niektórzy Pythonistas określiliby to jako „zły pomysł”, wprawia mnie w zakłopotanie, ale ... dla każdego z nich, jak sądzę?generalnie umieść
__iter__
metodę w swojej klasie i iteruj przez atrybuty obiektu lub umieść tę klasę mixin w swojej klasie.Twoja klasa:
źródło
one
itwo
jest zdefiniowane późniejyc = YourClass()
. Pytanie dotyczy przeglądania istniejących attris wYourClass()
. Ponadto dziedziczenieIterMixin
klasy może nie zawsze być dostępne jako rozwiązanie.vars(yc)
daje ten sam wynik bez konieczności dziedziczenia z innej klasy.vars(yc)
jest prawie taki sam, ale słownik, który Ci zwraca, należy do instancji__dict__
, więc zmodyfikowanie go zostanie odzwierciedlone w instancji. Może to prowadzić do problemów, jeśli nie będziesz ostrożny, więc powyższa metoda może czasami być lepsza (chociaż skopiowanie słownika jest prawdopodobnie łatwiejsze). Zwróć również uwagę, że chociaż słownik zwrócony powyżej nie należy do instancji__dict__
, wartości są takie same, więc modyfikowanie wszelkich zmiennych wartości będzie nadal odzwierciedlane w atrybutach instancji.Jak już wspomniano w niektórych odpowiedziach / komentarzach, obiekty Pythona już przechowują słownik ich atrybutów (metody nie są uwzględnione). Można to uzyskać w postaci
__dict__
, ale lepszym sposobem jest użycievars
(dane wyjściowe są jednak takie same). Zwróć uwagę, że modyfikowanie tego słownika spowoduje zmodyfikowanie atrybutów instancji! Może to być przydatne, ale oznacza również, że powinieneś ostrożnie korzystać z tego słownika. Oto krótki przykład:Używanie
dir(a)
jest dziwnym, jeśli nie wręcz złym podejściem do tego problemu. Dobrze, jeśli naprawdę potrzebujesz iteracji po wszystkich atrybutach i metodach klasy (w tym metodach specjalnych, takich jak__init__
). Jednak wydaje się, że nie jest to to, czego chcesz, a nawet zaakceptowana odpowiedź idzie źle, stosując trochę kruchego filtrowania, aby spróbować usunąć metody i pozostawić tylko atrybuty; możesz zobaczyć, jak to się nie powiedzie dla klasyA
zdefiniowanej powyżej.(Używanie
__dict__
zostało zrobione w kilku odpowiedziach, ale wszystkie definiują niepotrzebne metody zamiast używać ich bezpośrednio. Jedynie komentarz sugeruje użycievars
).źródło
a.b
w pewnym niestandardowej klasyB
następnievars(a)["b"] is a.b
, jak można by się spodziewać; nic innego nie miałoby sensu (myśleć oa.b
cukrze syntaktycznyma.__dict__["b"]
). Jeśli maszd = vars(a)
i wywołasz,repr(d)
to wywołarepr(d["b"])
jako część zwracania własnego ciągu repr, ponieważ tylko klasaB
naprawdę wie, jak powinien być reprezentowany jako łańcuch.Obiekty w Pythonie przechowują swoje atrybuty (w tym funkcje) w formie dict
__dict__
. Możesz (ale generalnie nie powinieneś) tego używać do bezpośredniego dostępu do atrybutów. Jeśli potrzebujesz tylko listy, możesz również wywołaćdir(obj)
, co zwraca iterowalną ze wszystkimi nazwami atrybutów, do których możesz następnie przekazaćgetattr
.Jednak konieczność robienia czegokolwiek z nazwami zmiennych jest zwykle złym projektem. Dlaczego nie przechowywać ich w kolekcji?
Następnie możesz iterować po kluczach za pomocą
for key in obj.special_values:
źródło
następnie nazwij to iterowalnym
źródło
Prawidłowa odpowiedź brzmi: nie powinieneś. Jeśli chcesz tego typu rzeczy, użyj po prostu dyktu lub będziesz musiał jawnie dodać atrybuty do jakiegoś kontenera. Możesz to zautomatyzować, ucząc się o dekoratorach.
W szczególności, nawiasem mówiąc, metoda method1 w twoim przykładzie jest równie dobra jak atrybut.
źródło
W przypadku Pythona 3.6
źródło
Jestem pewien, że Johan Cleeze pochwaliłby twój dogmatyzm;). Zostawiam tę odpowiedź, wciąż ją obwiniaj To właściwie czyni mnie bardziej powiernym. Zostaw komentarz kurczaki!
W przypadku Pythona 3.6
źródło