Jak mogę utworzyć obiekt i dodać do niego atrybuty?
Chcę utworzyć dynamiczny obiekt (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?
edit:
Ustawiam atrybuty z pętli for
, która przecina 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 otrzymałbym obj.a.attr1
, obj.a.attr2
, obj.a.attr3
.
Użyłem funkcji setattr
ponieważ nie wiedziałem jak zrobić obj.a.NAME
z for
pętla.
Jak ustawić atrybut na podstawie wartości p
w powyższym przykładzie?
15 answers
Możesz użyć mojego starożytnego przepisu Bunch , ale jeśli nie chcesz tworzyć" klasy bunch", bardzo prosta już istnieje w Pythonie - wszystkie funkcje mogą mieć dowolne atrybuty (w tym funkcje lambda). Tak więc następujące dzieła:
obj = someobject
obj.a = lambda: None
setattr(obj.a, 'somefield', 'somevalue')
Czy utrata jasności w porównaniu z przepisem czcigodnego jest OK, to decyzja stylowa, którą oczywiście pozostawiam tobie.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-13 14:49:46
Wbudowany object
może być utworzony, ale nie może mieć żadnych atrybutów ustawionych na nim. (Chciałbym, żeby mogło, w tym właśnie celu.) Nie posiada __dict__
do przechowywania atrybutów.
Generalnie robię to:
class Object(object):
pass
a = Object()
a.somefield = somevalue
Kiedy Mogę, nadaję Object
klasie bardziej wymowną nazwę, w zależności od tego, jakie dane w niej umieszczam.
Niektórzy ludzie robią inną rzecz, gdzie używają podklasy dict
, która umożliwia dostęp do atrybutów, aby dostać się do kluczy. (d.key
zamiast d['key']
)
Edit: aby dodać do twojego pytania, użycie setattr
jest w porządku. Po prostu nie można używać setattr
na object()
instancjach.
params = ['attr1', 'attr2', 'attr3']
for p in params:
setattr(obj.a, p, value)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-13 15:02:11
Jest types.SimpleNamespace
klasa w Pythonie 3.3+:
obj = someobject
obj.a = SimpleNamespace()
for p in params:
setattr(obj.a, p, value)
# obj.a.attr1
collections.namedtuple
, typing.NamedTuple
może być używany dla obiektów niezmiennych. PEP 557 -- Klasy danych sugeruje zmienną alternatywę.
Aby uzyskać bogatszą funkcjonalność, możesz wypróbować attrs
pakiet . Zobacz przykładowe użycie .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-13 18:02:23
Jest kilka sposobów na osiągnięcie tego celu. Zasadniczo potrzebujesz obiektu, który można rozszerzyć.
obj.a = type('Test', (object,), {})
obj.a.b = 'fun'
obj.b = lambda:None
class Test:
pass
obj.c = Test()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-05 14:16:21
Teraz możesz zrobić (Nie wiem czy to ta sama odpowiedź co evilpie):
MyObject = type('MyObject', (object,), {})
obj = MyObject()
obj.value = 42
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-13 00:32:55
Moduł mock
jest w zasadzie do tego stworzony.
import mock
obj = mock.Mock()
obj.a = 5
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-09 15:47:27
Wypróbuj poniższy kod:
$ python
>>> class Container(object):
... pass
...
>>> x = Container()
>>> x.a = 10
>>> x.b = 20
>>> x.banana = 100
>>> x.a, x.b, x.banana
(10, 20, 100)
>>> dir(x)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'banana']
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-10 13:03:54
As docs say:
Uwaga:
object
czy nie mA__dict__
, więc nie można przypisać dowolnych atrybutów do instancji klasyobject
.
Możesz po prostu użyć instancji dummy-class.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-13 14:43:29
Możesz również użyć obiektu klasy bezpośrednio; tworzy on Przestrzeń nazw:
class a: pass
a.somefield1 = 'somevalue1'
setattr(a, 'somefield2', 'somevalue2')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-18 18:13:43
Te rozwiązania są bardzo pomocne podczas testów. Bazując na odpowiedziach innych robię to w Pythonie 2.7.9 (bez staticmethod dostaję TypeError (niezwiązana metoda...):
In [11]: auth = type('', (), {})
In [12]: auth.func = staticmethod(lambda i: i * 2)
In [13]: auth.func(2)
Out[13]: 4
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-27 20:34:35
Jakich obiektów używasz? Po prostu próbowałem tego z przykładową klasą i działało dobrze:
class MyClass:
i = 123456
def f(self):
return "hello world"
b = MyClass()
b.c = MyClass()
setattr(b.c, 'test', 123)
b.c.test
I mam 123
jako odpowiedź.
Jedyną sytuacją, w której widzę to niepowodzenie, jest próba setattr
na zbudowanym obiekcie.
Update: z komentarza wynika powtórzenie: dlaczego nie można dodać atrybutów do obiektu w Pythonie?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:48
di = {}
for x in range(20):
name = '_id%s' % x
di[name] = type(name, (object), {})
setattr(di[name], "attr", "value")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-27 19:41:59
Coming to this late in the day, ale oto mój pennyworth z obiektem, który po prostu zdarza się trzymać kilka przydatnych ścieżek w aplikacji, ale możesz dostosować go do wszystkiego, gdzie chcesz pewien dict informacji, do których możesz uzyskać dostęp za pomocą notacji getattr i kropki (co jest tym, co myślę, że to pytanie jest naprawdę o): {]}
import os
def x_path(path_name):
return getattr(x_path, path_name)
x_path.root = '/home/x'
for name in ['repository', 'caches', 'projects']:
setattr(x_path, name, os.path.join(x_path.root, name))
To jest fajne bo teraz:
In [1]: x_path.projects
Out[1]: '/home/x/projects'
In [2]: x_path('caches')
Out[2]: '/home/x/caches'
Więc to używa obiektu function, jak powyższe odpowiedzi, ale używa funkcji, aby uzyskać wartości (możesz nadal używać (getattr, x_path, 'repository')
zamiast x_path('repository')
jeśli wolisz).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-02 02:17:04
W inny sposób widzę, w ten sposób:
import maya.cmds
def getData(objets=None, attrs=None):
di = {}
for obj in objets:
name = str(obj)
di[name]=[]
for at in attrs:
di[name].append(cmds.getAttr(name+'.'+at)[0])
return di
acns=cmds.ls('L_vest_*_',type='aimConstraint')
attrs=['offset','aimVector','upVector','worldUpVector']
getData(acns,attrs)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-13 18:04:39
Wszystko jest w dokumentach .
TLDR: musisz potwierdzić return_value
własność mocka, reszta to 'magia'.
Przykład:
SomeConstructor = MagicMock()
SomeConstructor.return_value. \
some_class_method.assert_called_once_with('cool!')
SomeConstructor.return_value. \
some_inner_property. \
some_inner_method.assert_called_once_with('super cool!')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-31 12:10:58