Как получить переменные экземпляра в Python?

Есть ли в Python встроенный метод для получения массива всех переменных экземпляра класса? Например, если у меня есть этот код:

class hi:
  def __init__(self):
    self.ii = "foo"
    self.kk = "bar"

Есть ли у меня способ сделать это:

>>> mystery_method(hi)
["ii", "kk"]

Обновлено: изначально я ошибочно запрашивал переменные класса.

В вашем примере показаны «переменные экземпляра». Другое дело - переменные класса.

S.Lott 20.09.2008 23:37
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
133
1
155 559
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Ответ принят как подходящий

У каждого объекта есть переменная __dict__, содержащая все переменные и ее значения.

Попробуй это

>>> hi_obj = hi()
>>> hi_obj.__dict__.keys()

FWIW, модуль проверки дает вам более надежный метод, чем полагаться на диктовать, который есть не во всех экземплярах.

Thomas Wouters 20.09.2008 23:40

У какого экземпляра нет диктовать? Никогда не встречал.

Carl Meyer 21.09.2008 03:37

Некоторые встроенные типы, например int. Попробуйте сказать «x = 5», а затем «x .__ dict__», и вы получите AttributeError.

Eli Courtwright 21.09.2008 09:47

Также все, что использует слоты.

Thomas Wouters 21.09.2008 12:41

Зачем вам пытаться получить переменные экземпляра класса int? Это даже не класс (хотя я могу ошибаться в этом).

Martin Sherburn 20.10.2010 18:34

Также re.MatchObjects (без __dict__)

hobs 18.03.2012 07:52

@MartinSherburn Потому что кто-то может захотеть получить переменные экземпляров, заранее зная, какие типы будут встречаться.

einnocent 01.02.2014 02:12

Как выглядит пример вывода для этого кода?

Stevoisiak 06.02.2018 22:25

Также numpy ndarrays возвращает AttributeError, когда вы пытаетесь получить доступ к их атрибутам с помощью __dict__

dbouz 16.09.2019 17:55

Обычно вы не можете получить атрибуты экземпляра, заданные только классом, по крайней мере, без создания экземпляра класса. Однако вы можете получить атрибуты экземпляра для данного экземпляра или атрибуты класса для класса. См. Модуль «инспектировать». Вы не можете получить список атрибутов экземпляра, потому что экземпляры действительно могут иметь что угодно в качестве атрибута, и - как в вашем примере - обычный способ их создания - просто назначить им в методе __init__.

Исключением является случай, если ваш класс использует слоты, которые представляют собой фиксированный список атрибутов, которые класс разрешает иметь экземплярам. Слоты объясняются в http://www.python.org/2.2.3/descrintro.html, но со слотами есть различные подводные камни; они влияют на структуру памяти, поэтому множественное наследование может быть проблематичным, и при наследовании в целом также необходимо учитывать слоты.

Голосование вниз, потому что «вы не можете получить список атрибутов экземпляра», просто неверно: и vars (), и диктовать дают вам именно это.

Carl Meyer 21.09.2008 03:43

Я предполагаю, что он имел в виду «вы не можете получить список всех возможных атрибутов экземпляра». Например, я часто использую ленивую генерацию и декоратор @property для добавления переменной экземпляра при первом запросе. Использование диктовать сообщит вам об этой переменной, когда она существует, но не заранее.

Eli Courtwright 21.09.2008 09:51

Я не голосовал против, и обратите внимание на то, что я на самом деле сказал: вы не можете получить список атрибутов экземпляра учитывая просто класс, что и пытается сделать код, сопровождающий вопрос.

Thomas Wouters 21.09.2008 20:00

@Carl: Пожалуйста, учитесь перед тем, как писать ложные комментарии и голосовать против, исходя из вашего незнания.

nikow 06.05.2009 23:28

Вы также можете проверить, есть ли у объекта конкретная переменная:

>>> hi_obj = hi()
>>> hasattr(hi_obj, "some attribute")

В вашем примере показаны «переменные экземпляра», а не переменные класса.

Найдите в hi_obj.__class__.__dict__.items() переменные класса, а также другие члены класса, такие как функции-члены и содержащий модуль.

class Hi( object ):
    class_var = ( 23, 'skidoo' ) # class variable
    def __init__( self ):
        self.ii = "foo" # instance variable
        self.jj = "bar"

Переменные класса используются всеми экземплярами класса.

Используйте vars ()

class Foo(object):
    def __init__(self):
        self.a = 1
        self.b = 2

vars(Foo()) #==> {'a': 1, 'b': 2}
vars(Foo()).keys() #==> ['a', 'b']

+1 Я лично считаю, что этот синтаксис чище, чем использование диктовать, поскольку атрибуты с двойным подчеркиванием должны быть «частными» в синтаксисе Python.

Martin W 21.09.2008 00:30

@Martin: __method является частным, __method__ - специальным методом, не обязательно частным; Я хотел бы сказать, что специальные методы определяют возможности объекта, а не методы.

u0b34a0f6ae 11.10.2009 20:32

__method__ довольно уродлив, и я думаю, что они были названы так, чтобы попытаться удержать людей от их использования без крайней необходимости. В этом случае у нас есть альтернативный вариант vars ().

Martin Sherburn 10.11.2010 18:32

в моем случае я попытался вызвать vars (ObjName), и он возвращает dict_proxy со словарем, ключи которого являются методами данного класса / объекта, но без признаков элементов в этом. Есть догадки, почему?

user228137 05.05.2014 20:29

Переменные двойного подчеркивания __str__, __method__ обычно относятся к самому языку. Что происходит при использовании str(something)?

Zizouz212 10.05.2015 22:28

Предложить

>>> print vars.__doc__
vars([object]) -> dictionary

Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.

Другими словами, он просто обертывает __dict__

Хотя это и не прямой ответ на вопрос OP, есть довольно приятный способ узнать, какие переменные находятся в области видимости функции. взгляните на этот код:

>>> def f(x, y):
    z = x**2 + y**2
    sqrt_z = z**.5
    return sqrt_z

>>> f.func_code.co_varnames
('x', 'y', 'z', 'sqrt_z')
>>> 

Атрибут func_code содержит много интересного. Это позволяет делать классные вещи. Вот пример того, как я это использовал:

def exec_command(self, cmd, msg, sig):

    def message(msg):
        a = self.link.process(self.link.recieved_message(msg))
        self.exec_command(*a)

    def error(msg):
        self.printer.printInfo(msg)

    def set_usrlist(msg):
        self.client.connected_users = msg

    def chatmessage(msg):
        self.printer.printInfo(msg)

    if not locals().has_key(cmd): return
    cmd = locals()[cmd]

    try:
        if 'sig' in cmd.func_code.co_varnames and \
                       'msg' in cmd.func_code.co_varnames: 
            cmd(msg, sig)
        elif 'msg' in cmd.func_code.co_varnames: 
            cmd(msg)
        else:
            cmd()
    except Exception, e:
        print '\n-----------ERROR-----------'
        print 'error: ', e
        print 'Error proccessing: ', cmd.__name__
        print 'Message: ', msg
        print 'Sig: ', sig
        print '-----------ERROR-----------\n'

Оба метода Vars () и dict будут работать для примера, опубликованного OP, но они не будут работать для "слабо" определенных объектов, таких как:

class foo:
  a = 'foo'
  b = 'bar'

Чтобы распечатать все невызываемые атрибуты, вы можете использовать следующую функцию:

def printVars(object):
    for i in [v for v in dir(object) if not callable(getattr(object,v))]:
        print '\n%s:' % i
        exec('print object.%s\n\n') % i

exec('print object.%s\n\n') % i должен быть записан как print getattr(object, i).

user102008 06.01.2011 01:18

построен на ответе dmark, чтобы получить следующее, что полезно, если вам нужен эквивалент sprintf и, надеюсь, поможет кому-то ...

def sprint(object):
    result = ''
    for i in [v for v in dir(object) if not callable(getattr(object, v)) and v[0] != '_']:
        result += '\n%s:' % i + str(getattr(object, i, ''))
    return result

Иногда вам нужно отфильтровать список на основе общедоступных / частных переменных. Например.

def pub_vars(self):
    """Gives the variable names of our instance we want to expose
    """
    return [k for k in vars(self) if not k.startswith('_')]

Вам потребуется сначала изучить класс, затем проверить байт-код на наличие функций, затем скопировать байт-код и, наконец, используйте __code__.co_varnames. Это сложно, потому что некоторые классы создают свои методы с помощью конструкторов, подобных тем, что используются в модуле types.. Я предоставлю его код на GitHub.

Другие вопросы по теме