Chcę utworzyć obiekt dynamiczny (wewnątrz innego obiektu) w Pythonie, a następnie dodać do niego atrybuty.
Próbowałem:
obj = someobject
obj.a = object()
setattr(obj.a, 'somefield', 'somevalue')
ale to nie zadziałało.
Jakieś pomysły?
edytować:
Ustawiam atrybuty z for
pętli, która przechodzi przez listę wartości, np
params = ['attr1', 'attr2', 'attr3']
obj = someobject
obj.a = object()
for p in params:
obj.a.p # where p comes from for loop variable
W powyższym przykładzie chciałbym uzyskać obj.a.attr1
, obj.a.attr2
, obj.a.attr3
.
Użyłem tej setattr
funkcji, ponieważ nie wiedziałem, jak to zrobić obj.a.NAME
z for
pętli.
Jak ustawić atrybut na podstawie wartości z p
powyższego przykładu?
a = object()
i potrzebujeszobj.a = object()
. Ponownie mówię o przykładzie, w twoim rzeczywistym kodzie może się przydać obiekt wewnątrz obiektu.Odpowiedzi:
Możesz użyć mojej starożytnej receptury Bunch , ale jeśli nie chcesz tworzyć „klasy pęczka”, w Pythonie istnieje już bardzo prosta - wszystkie funkcje mogą mieć dowolne atrybuty (w tym funkcje lambda). Tak więc następujące prace:
To, czy utrata jasności w porównaniu z czcigodnym
Bunch
przepisem jest w porządku, jest decyzją stylową, którą oczywiście podejmę.źródło
lambda: 23
), więc do takich ekspertów używającychlambda
s do tego celu prawdopodobnie nie czułby się niczym „hack”. Osobiście nie bardzo lubięlambda
w Pythonie - ale to kwestia osobistego gustu.lambda
wzorzec pasuje do twojego przypadku użycia, może doprowadzić do uświadomienia sobie, że coś, co pierwotnie uważałeś za dane, jest w rzeczywistości bardziej jak funkcja - lub, w każdym razie, funktorem.from argparse import Namespace
choć chciałbym, żeby mieszkał gdzie indziej * np.collection
) - ponownie wykorzystując już istniejący typ, po prostu lepszy i wciąż unikając tworzenia nowego typu. Ale wtedy go tam nie było :-).Wbudowane
object
mogą być tworzone instancje, ale nie mogą mieć ustawionych żadnych atrybutów. (Chciałbym, żeby mógł, właśnie w tym celu.) Nie ma__dict__
posiadać atrybutów.Zasadniczo po prostu to robię:
Kiedy mogę, daję
Object
nadaję klasie bardziej znaczącą nazwę, w zależności od tego, jakie dane w niej umieszczam.Niektóre osoby robią coś innego, wykorzystując ich podklasę,
dict
która umożliwia dostęp do atrybutów w celu uzyskania kluczy. (d.key
zamiastd['key']
)Edycja : Do dodania do pytania użycie
setattr
jest w porządku. Po prostu nie możesz używaćsetattr
wobject()
instancjach.źródło
foo = object()
działa, ale po prostu niewiele można z tym zrobićtype....
lub lambda nigdy nie było moją ulubioną, podobnie jak wymioty tekstowe w moim kodzie. Ale ten pomysł jest świetny do używania obiektów do przechowywania właściwości. Pozostawia kod bardziej czytelny b / c, gdy widzę lambda Zwalniam czytanie do 25%, podczas gdy twoja droga ma sens! Dzięki.Struct
nazwy klasy, aby uczynić ją bardziej oczywistą. Zaoszczędził mi mnóstwo pisania["
i"]
, Na zdrowie!W
types.SimpleNamespace
Python 3.3+ istnieje klasa :collections.namedtuple
,typing.NamedTuple
może być stosowany do obiektów niezmiennych. PEP 557 - Klasy danych sugerują zmienną alternatywę.Aby uzyskać bogatszą funkcjonalność, możesz wypróbować
attrs
pakiet . Zobacz przykładowe użycie .źródło
argparse.Namespace
klasęattrs
Pakiet @Roel obsługuje Python 2.7Istnieje kilka sposobów na osiągnięcie tego celu. Zasadniczo potrzebujesz obiektu, który można rozszerzyć.
źródło
obj.a = type('', (), {})
mock
Moduł jest w zasadzie wykonane za to.źródło
unittest.Mock
jest częścią standardowej biblioteki od Python 3.3 ( docs.python.org/3/library/unittest.mock.html )mock
w nim trochę . Po prostu czuję się dziwnie.Teraz możesz zrobić (nie jestem pewien, czy to ta sama odpowiedź, co zło):
źródło
Wypróbuj poniższy kod:
źródło
Możesz także użyć bezpośrednio obiektu klasy; tworzy przestrzeń nazw:
źródło
jak mówią doktorzy :
Możesz po prostu użyć instancji klasy fikcyjnej.
źródło
Te rozwiązania są bardzo pomocne podczas testowania. Opierając się na odpowiedziach innych osób, robię to w Pythonie 2.7.9 (bez metody static otrzymuję TypeError (niezwiązana metoda ...):
źródło
Z jakich obiektów korzystasz? Właśnie wypróbowałem to na przykładowej klasie i działało dobrze:
I dostałem
123
jako odpowiedź.Jedyną sytuacją, w której widzę ten błąd, jest próba
setattr
użycia wbudowanego obiektu.Aktualizacja: Z komentarza jest to powtórzenie: Dlaczego nie możesz dodawać atrybutów do obiektu w pythonie?
źródło
Przybywam do późna w ciągu dnia, ale tutaj jest moja grosza z obiektem, który akurat zawiera pewne przydatne ścieżki w aplikacji, ale możesz go dostosować do dowolnego miejsca, w którym chcesz uzyskać swoisty słownik informacji, do których możesz uzyskać dostęp za pomocą notacji getattr i kropki (o czym myślę, że tak naprawdę chodzi o to pytanie):
To jest fajne, ponieważ teraz:
Używa to obiektu funkcyjnego jak powyższe odpowiedzi, ale używa funkcji do uzyskania wartości (nadal możesz używać,
(getattr, x_path, 'repository')
a niex_path('repository')
wolisz).źródło
Jeśli potrafimy ustalić i zsumować wszystkie atrybuty i wartości razem przed utworzeniem zagnieżdżonego obiektu, moglibyśmy stworzyć nową klasę, która pobiera argument słownika podczas tworzenia.
Możemy również zezwolić na argumenty słów kluczowych. Zobacz ten post .
źródło
źródło
Innym sposobem widzę, w ten sposób:
źródło
class a: pass
daje całą wymaganą moc.