У меня есть объект python с несколькими атрибутами и методами. Я хочу выполнять итерации по атрибутам объекта.
class my_python_obj(object):
attr1='a'
attr2='b'
attr3='c'
def method1(self, etc, etc):
#Statements
Я хочу сгенерировать словарь, содержащий все атрибуты объекта и их текущие значения, но я хочу сделать это динамически (так что если позже я добавлю еще один атрибут, мне не придется помнить, что нужно обновить и мою функцию).
В php в качестве ключей можно использовать переменные, но объекты в python не поддаются расшифровке, и если я использую для этого точечную нотацию, то создается новый атрибут с именем моего var, что не входит в мои планы.
Просто чтобы прояснить ситуацию:
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
Обновление: Под атрибутами я подразумеваю только переменные этого объекта, а не методы.
Предположим, что у вас есть такой класс, как
>>> class Cls(object):
... foo = 1
... bar = 'hello'
... def func(self):
... return 'call me'
...
>>> obj = Cls()
вызов dir
на объекте возвращает вам все атрибуты этого объекта, включая специальные атрибуты python. Хотя некоторые атрибуты объекта можно вызывать, например, методы.
>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo', 'func']
Вы всегда можете отфильтровать специальные методы с помощью понимания списка.
>>> [a for a in dir(obj) if not a.startswith('__')]
['bar', 'foo', 'func']
или, если вы предпочитаете map/filters.
>>> filter(lambda a: not a.startswith('__'), dir(obj))
['bar', 'foo', 'func']
Если вы хотите отфильтровать методы, вы можете использовать встроенный ``callable'' в качестве проверки.
>>> [a for a in dir(obj) if not a.startswith('__') and not callable(getattr(obj, a))]
['bar', 'foo']
Вы также можете проверить разницу между вашим классом и его объектом экземпляра, используя.
>>> set(dir(Cls)) - set(dir(object))
set(['__module__', 'bar', 'func', '__dict__', 'foo', '__weakref__'])
в общем поставил __ИТЭР__
метод в класс и просмотреть атрибуты объекта или поместить этот класс mixin в своем классе.
class IterMixin(object):
def __iter__(self):
for attr, value in self.__dict__.iteritems():
yield attr, value
Ваш класс:
>>> class YourClass(IterMixin): pass
...
>>> yc = YourClass()
>>> yc.one = range(15)
>>> yc.two = 'test'
>>> dict(yc)
{'one': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 'two': 'test'}
Объекты в python хранят свои атрибуты (включая функции) в дикте под названием __dict__
. Вы можете (но обычно не должны) использовать его для прямого доступа к атрибутам. Если вам нужен только список, вы также можете вызвать dir(obj)
, который возвращает итерабельную таблицу со всеми именами атрибутов, которые вы можете передать в getattr
.
Однако необходимость что-то делать с именами переменных обычно является плохим решением. Почему бы не хранить их в коллекции?
class Foo(object):
def __init__(self, **values):
self.special_values = values
Затем вы можете перебирать ключи с помощью команды for key in obj.special_values:
.
Как указывалось в некоторых ответах/комментариях уже, питона объекты уже хранить словарь их атрибуты (методы разве'т в комплекте). Это могут быть доступны как __дикт__
, но лучше использовать Варс
(выход такой же, правда). Обратите внимание, что изменение этого словаря будет изменять атрибуты экземпляра! Это может быть полезно, но также означает, что вы должны быть осторожны, как вы используете этот словарь. Здесь'краткий пример:
``питон класс A(): деф инит(самостоятельная, х=3, У=2 и Z=5): самовывоз.х = х самовывоз._y = г самовывоз.з = з
Дэф Ф(самовыдвижение): пройти
а = а() печати(Варс(а))
а.х = 10 печати(Варс(а))
Варс(с)["и _y" с] = 20 печати(Варс(а))
``
Используя Дир(а) - это странно, если не сказать плохо, подход к этой проблеме. Это's хорошо, если вам действительно нужно, чтобы перебрать все атрибуты и методы класса (в том числе специальных методов, таких как __init и__
). Однако, это не'т, кажется, чтобы быть то, что вы хотите, и даже принято отвечать об этом-плохо, применяя некоторые хрупкие фильтрации с целью удаления методы и атрибуты, вы можете увидеть, как это будет плохо для класса " А " определен выше.
(используя __дикт__
было сделано через пару ответов, но они все определяют ненужные методы, а не использовать его напрямую. Только комментарий предлагает использовать Варс
).
class someclass:
x=1
y=2
z=3
def __init__(self):
self.current_idx = 0
self.items = ["x","y","z"]
def next(self):
if self.current_idx < len(self.items):
self.current_idx += 1
k = self.items[self.current_idx-1]
return (k,getattr(self,k))
else:
raise StopIteration
def __iter__(self):
return self
тогда просто назови его как итерируемый
s=someclass()
for k,v in s:
print k,"=",v
Правильный ответ на этот вопрос заключается в том, что вы не должны этого делать. Если вам нужны подобные вещи, либо просто используйте dict, либо вам нужно явно добавить атрибуты к какому-то контейнеру. Это можно автоматизировать, изучив декораторы.
В частности, кстати, method1 в вашем примере является таким же хорошим атрибутом.
Для Python 3.6
class SomeClass:
def attr_list(self, should_print=False):
items = self.__dict__.items()
if should_print:
[print(f"attribute: {k} value: {v}") for k, v in items]
return items
Для Python 3.6
class SomeClass:
def attr_list1(self, should_print=False):
for k in self.__dict__.keys():
v = self.__dict__.__getitem__(k)
if should_print:
print(f"attr: {k} value: {v}")
def attr_list(self, should_print=False):
b = [(k, v) for k, v in self.__dict__.items()]
if should_print:
[print(f"attr: {a[0]} value: {a[1]}") for a in b]
return b