2013-04-18 3 views
0

Атрибут экземпляров класса очень полезен для сопоставления заданного объекта dict с экземпляром класса (ключи ключа, которые в процессе обрабатывают атрибуты экземпляра класса).Сопоставление элементов dict по атрибутам класса

Пример:

>>> class SomeClass(object): 
...  def __init__(self): 
...   self.numbers = [1, 3, 5, 7, 9] 
... 
>>> inst = SomeClass() 
>>> inst.__dict__ 
{'numbers': [1, 3, 5, 7, 9]} 
>>> inst.__dict__.update({ 
...  'letters': ['a', 'b', 'c', 'd'], 
...  'numbers': [2, 4, 6, 8, 10] 
...  }) 
>>> inst.letters, inst.numbers 
(['a', 'b', 'c', 'd'], [2, 4, 6, 8, 10]) 

Однако, это не будет работать, если атрибуты класса объявляются следующим образом:

>>> class SomeClass(object): 
...  numbers = [1, 3, 5, 7, 9] 
... 
>>> inst = SomeClass() 
>>> inst.__dict__ 
{} 

Есть ли способ, чтобы иметь доступ к ним в этом случае? Я имею в виду, есть ли способ перечислить их независимо от других атрибутов специального класса, таких как методы или атрибуты по умолчанию?

ответ

1

Мой совет, что вы должны избегать изменения __dict__, locals() и так далее ,

Почему явным образом не сохраняю атрибуты, которые вы ожидаете быть динамическими в словаре? Таким образом, вы не получите кучу объектов вокруг с атрибутами, которых вы не ожидали, потому что они не были определены в классе и были обезглавлены кодом где-то в другом месте.

Я думаю, что это намного яснее и менее страшно:

class MyClass(object): 
    classattrs = {'numbers': [1,2,3,4,5]} 

MyClass.classattrs['letters'] = ['a','b','c'] 

Она сводится к тому, что люди ожидают содержимое Словаре изменить.Они не ожидают изменения атрибутов класса.

В любом случае, inspect, dir и их ilk будут иметь проблемы с фильтрацией всех других атрибутов класса, таких как специальные методы и т. Д.

Эта идея сохранения имен и атрибутов (разумно) Статическая было выражено людьми намного умнее и опытнее меня: http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html

+0

Я понимаю смысл, но в моей конкретной ситуации нет проблем с изменением атрибутов «на лету». Если я это сделаю, это потому, что я считаю (как это ни парадоксально) более простым. – michaelmeyer

+0

На твоей собственной голове! Если вам нужен список всех атрибутов, которые не являются «волшебными», вы можете попробовать отфильтровать все имена с двойным подчеркиванием с помощью 'inspect.getmembers' - что-то вроде этого:' [name, attr for name, attr in inspect.getmembers (MyClass), если не name.startswith ('__'), а не inspect.ismethod (attr)] ' –

+0

* Это * страшно! :) Поэтому, кажется, я ошибаюсь, пытаясь это сделать. Я попытаюсь найти другой путь. Спасибо за совет ! – michaelmeyer

3

Это класс атрибуты, а не атрибуты экземпляров. Атрибуты класса разделяются между экземплярами. Это также то, как экземпляры наследуют методы своего класса. Атрибуты экземпляра с одинаковыми атрибутами теневого класса, поэтому вы можете установить numbers на экземпляр, чтобы предоставить экземпляру его собственную копию.

Вы можете использовать dir() на примере перечислить комбинированный вид экземпляра и атрибута класса имен:

>>> inst = SomeClass() 
>>> dir(inst) 
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'numbers'] 

Вы можете использовать inspect.getmembers() фильтровать по типу атрибута.

Другой вариант заключается в пропишите класс атрибуты с __dict__:

>>> vars(type(inst)) 
dict_proxy({'__dict__': <attribute '__dict__' of 'SomeClass' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'SomeClass' objects>, 'numbers': [1, 3, 5, 7, 9], '__doc__': None}) 
>>> {k: v for k, v in vars(type(inst)).iteritems() if not k.startswith('__') and not inspect.isfunction(v)} 
{'numbers': [1, 3, 5, 7, 9]} 

От Class definitions documentation:

Переменные, определенные в определении класса являются атрибутами класса; они разделяются экземплярами. Атрибуты экземпляра могут быть установлены в методе с self.name = value. Оба атрибута класса и экземпляра доступны через нотацию «self.name», и атрибут экземпляра скрывает атрибут класса с тем же именем при обращении таким образом.

+0

Я знал, что 'dir' вещь, но не' inspect.getmembers'. Тем не менее, они кажутся непригодными для меня в моем случае без использования уродливого взлома. – michaelmeyer

1

Если определить numbers как атрибут класса,

class SomeClass(object): 
    numbers = [1, 3, 5, 7, 9] 

, то он помещается в SomeClass.__dict__:

In [5]: SomeClass.__dict__ 
Out[5]: dict_proxy(
{'__dict__': <attribute '__dict__' of 'SomeClass' objects>, 
'__module__': '__main__', 
'__weakref__': <attribute '__weakref__' of 'SomeClass' objects>, 
'numbers': [1, 3, 5, 7, 9], 
'__doc__': None}) 
Смежные вопросы