2015-08-07 3 views
4

Я смотрю на исходный код для trie implementationМагические методы и определение порядка

В строках 80-85:

def keys(self, prefix=[]): 
    return self.__keys__(prefix) 

def __keys__(self, prefix=[], seen=[]): 
    result = [] 
    etc. 
  1. Что такое def __keys__? Это волшебный объект, который создан самостоятельно? Если да, то этот плохой код? Или __keys__ существуют в качестве стандартного метода магии Python? Однако я не могу найти его нигде в документации Python.

  2. Почему это законно для функции для звонка self.__keys__ до того, как def __keys__ даже экземпляр? Не было def __keys__ должно быть раньше def keyskeys звонки __keys__)?

+0

- это код, инкапсулированный в 'class ..:'? или это файл .py? (да, это важно для моего объяснения) – Henrik

+0

@ Хенрик, возможно, посмотрите ссылку на источник? – Enerccio

+0

'def keys' определяет функцию' keys', она фактически не называет 'self .__ keys__', пока кто-то не называет ее, например. 'Trie.keys()'. К этому моменту будет определено '__keys__'. –

ответ

-1

Компиляция класса в Python выполняется до создания экземпляра класса.

Всякий раз, когда тип класса создается, тело блока класса скомпилировано и выполнено. Затем все функции преобразуются либо в связанные ручки (обычные функции), либо в объекты classmethod/staticmethod. Затем, когда создается новый экземпляр, содержимое типа __dict__ копируется в экземпляр (а связанные ручки преобразуются в методы).

Таким образом, в момент вызова instance.keys() экземпляр уже имеет как keys, так и __keys__ методов.

Кроме того, нет никакого метода __keys__ в любом режиме данных, насколько мне известно.

+2

Ваше описание того, как создаются объекты, не очень точно применимо к классам нового стиля (которые являются единственным видом в Python 3). Хотя связанный класс не имеет 'object' в качестве базы, он, вероятно, должен! В классах нового стиля определенные функции не превращаются ни в какие специальные (если только они не оформлены). Это происходит только тогда, когда они ищут экземпляр, с которым они связаны (через протокол дескриптора). Кроме того, ничто не копируется из класса '__dict__' в экземпляр' __dict__', так как поиск атрибутов проверяет в классе dict (и dicts любых баз), если это необходимо. – Blckknght

+0

@Blckknght насколько я знаю, все все еще копируется в экземпляр, потому что если вы попробуете переменную класса, вы можете изменить копию в экземпляре без модификации переменной класса. Кроме того, функция может быть изменена на связанные объекты в python2 даже с новыми классами стилей (Foo.method является связанной функцией, потому что для Foo требуется первый аргумент). – Enerccio

+1

Ничего не копируется автоматически в экземпляр dict. Ваша переменная класса «изменено», вероятно, восстанавливается как переменная экземпляра, так что она меняет прежнее значение, а не изменяется на месте. Что касается методов, вы отчасти правы, что в Python 2 вы получаете специальный вид «несвязанного» метода при поиске метода в классе, но вы ошибаетесь в том, когда это происходит. Это происходит только тогда, когда вы выполняете поиск, связанный с привязкой. Если вы посмотрите в классе '__dict__', вы увидите немодифицированную функцию. – Blckknght

2

Для вашего второго вопроса, это законно, функции для класса определяются, когда класс определяется, поэтому вы можете быть уверены, что обе функции будут определены до того, как будет вызываться keys(), логика также применима к нормальным функциям, мы может сделать -

>>> def a(): 
...  b() 
... 
>>> def b(): 
...  print("In B()") 
... 
>>> a() 
In B() 

Это является законным, поскольку оба a() и b() были определены до a() называется. Это было бы незаконным, если вы попытаетесь позвонить a() до того, как будет определено значение b(). Обратите внимание, что определение функции автоматически не вызывает ее, и python не проверяет во время определения функции, независимо от того, определены или нет функции, используемые в функции (до исполнения, когда функция вызывается, и в этом случае она выдает NameError)

Для вашего первого вопроса, я не знаю таких магических методов, которые называются __keys__(), не может найти его в документации.

2

Все реальные «магические методы» находятся в data model documentation; __keys__ не является одним из них. style guide говорит:

Никогда не изобретайте такие названия; используйте их только как задокументированные.

так да, составление нового - плохая форма (соглашение было бы назвать это _keys).

Вторая часть вашего вопроса не имеет смысла; даже если это не был класс, нет необходимости определять методы и функции в том порядке, в котором они вызываются. Пока они существуют к тому времени, когда звонок действительно будет сделан, это не проблема. Я склонен определять общественные методы перед частными, хотя первый может назвать последний, просто для удобства читателя.

0
  1. Не существует волшебного метода с именем __keys__(), так как вы подозревали, что это просто плохое имя.

  2. Код в определении класса может быть в любом порядке. Все те вопросы, которые были сделаны определением к моменту фактического вызова, выполняются ниже по течению.

0

Существует не магический метод с именем __keys__, поэтому его просто неправильное соглашение об именах. Глядя на код, автор просто хотел иметь частный метод, который используется внутри, а также из общедоступного метода keys. Как видите, __keys__ принимает дополнительный аргумент.

О втором вопросе нет необходимости определять функции в том же порядке, в каком они были вызваны. Он будет доступен по временному коду.

Смежные вопросы