#python #dictionary #lookup #member
#python #словарь #поиск #Участник
Вопрос:
В Python, если я определю три класса:
class A:
name = 'oliver'
hailstone_ending = [4,2,1]
class B:
def __init__(self):
self.name = 'oliver'
self.hailstone_ending = [4,2,1]
class C:
pass
c = C()
c.name = 'oliver'
c.hailstone_ending = [4,2,1]
Под капотом функция поиска членов одинакова для каждого класса? Похоже, что A
для поиска членов для всех экземпляров потребуется только словарь; C
с другой стороны, потребуется использовать словарь, хранящийся в каждом из этих экземпляров. Если бы интерпретатор был очень умным, он теоретически мог заметить, что все экземпляры B
must включают члены name
и hailstone_ending
; следовательно, это может быть эквивалентно A
.
Но, с другой стороны, если del
операция разрешена для словаря, который ищет членов класса, механизм поиска во всех этих классах может быть эквивалентным, поскольку доступные члены будут зависеть от экземпляра.
Меня интересует то, что у меня был некоторый код, который создавал несколько тысяч классов типа C
, и я заметил, что он был очень медленным и требовал много памяти. Недавно я переписал его по-другому, и он кажется более эффективным (но я не проверял его тщательно, и поэтому он может быть таким же).
Большое спасибо за ваше понимание!
Комментарии:
1. нет …
A
сильно отличается отB
. Интерпретатор достаточно умен, чтобы заметить это.
Ответ №1:
Под капотом функция поиска членов одинакова для каждого класса?
Если вы не переопределите __getattribute__
, поиск атрибутов сначала проверяет атрибуты объекта, а затем атрибуты типа. Неважно, как появился класс.
Похоже, что A потребуется только в словаре для поиска членов для всех экземпляров; C, с другой стороны, потребуется использовать словарь, хранящийся в каждом из этих экземпляров. Если бы интерпретатор был очень умным, он теоретически мог заметить, что все экземпляры B должны включать имена членов и hailstone_ending ; следовательно, это может быть эквивалентно A.
В A
, атрибуты хранятся в A.__dict__
, то есть в типе. В B
и C
атрибуты хранятся в self.__dict__
, то есть в экземпляре. Оба словаря присутствуют во всех случаях. Больше в этом ничего нет. И нет, нет никакой разницы между B
и C
.
Комментарии:
1. Одна настройка:
del
выполняет поиск атрибутов: он должен найти атрибут, чтобы удалить его. Помните: на самом деле он где-то удаляет атрибут из пространства имен, поэтому ему необходимо выполнить поиск. Ему не передается значение, которое было результатом поиска атрибута, поскольку тогда он потерял бы информацию о том, откуда взялся атрибут.
Ответ №2:
В python каждый класс и каждый экземпляр получает словарь. A
использует словарь класса. В примерах для классов B
и C
используются словари экземпляров. B
не будет эквивалентно A
— python не предназначен для быстрой работы, было бы очень сложно, если не невозможно, доказать, что никакие экземпляры B
не будут изменены.
Доказательство:
>>> class D:
... def __init__(self):
... self.a = 3
...
>>> d = D()
>>> d.a
3
>>> D.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: class D has no attribute 'a'
>>> dd = D()
>>> dd.a
3
>>> D.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: class D has no attribute 'a'
Ваш вопрос заставляет меня задуматься о прототипах javascript.
Также: поиск членов может возвращаться к словарю класса, если член не найден в словаре экземпляра, но при записи будет использоваться словарь экземпляра.
Комментарии:
1. Я знаю, что Python не создан для быстрой работы — мне часто это говорят. Просто в моем характере задаваться вопросом об этих вещах. Я научился программировать на графическом калькуляторе TI-85, и иногда бывает интересно узнать, как выжать скорость из маленьких скрытых мест. И это может быть действительно полезно, если вы застряли с чем-то, что просто не похоже, что это можно сделать быстрее!