2014-10-23 2 views
8

Обычный метод доступа к атрибутам требует, чтобы имена атрибутов были valid python identifiers.Атрибуты, которые не являются допустимыми идентификаторами python

Но атрибуты не должны быть допустимыми идентификаторами Python:

>>> class Thing: 
...  def __init__(self): 
...   setattr(self, '0potato', 123) 
...   
>>> t = Thing() 
>>> Thing.__getattribute__(t, '0potato') 
123 
>>> getattr(t, '0potato') 
123 

Конечно, t.0potato остается в SyntaxError, но атрибут является то, тем не менее:

>>> vars(t) 
{'0potato': 123} 

Что является причиной это допустимо? Есть ли действительно какой-либо допустимый прецедент для атрибутов с пробелами, пустой строкой, ключевыми словами с поддержкой python и т. Д.? Я думал, что причина в том, что атрибуты были только ключи в объекте/именах Dict, но это не имеет никакого смысла, так как другие объекты, которые являются допустимыми ключами Dict не допускаются:

>>> setattr(t, ('tuple',), 321) 
TypeError: attribute name must be string, not 'tuple' 
+2

Ответ на вопрос, почему это разрешено, можно найти в ответе @ poke [здесь] (http://stackoverflow.com/a/25477703/2555451).Я не думаю, что ваш вопрос должен быть забит, но потому, что он просит законных случаев использования, когда другой спрашивает, почему это разрешено. – iCodez

+0

Для начала см. Ответ Мартина против Лёвиса в [Python Issue 14029] (http://bugs.python.org/issue14029). Поэтому в основном это зависит от базовой реализации '__setattr__', которая может принимать неидентификаторы. Тем не менее, хотя можно создать '__setattr__', который принимает кортежи, но все равно терпит неудачу при вызове через' setattr'. Таким образом, кажется, что встроенный метод не просто слепо передает свои аргументы методу '__setattr__' объекта. –

+4

Здесь [Guido van Rossum рассматривает] (https://mail.python.org/pipermail/python-dev/2012-March/117441.html) ваш вопрос. –

ответ

0

Детали из comment на опубликовать полностью ответить на этот вопрос, поэтому я отправляю его в качестве ответа:

Guido говорит:

... это функция, что вы можете использовать любую строку с GetAttr() и setattr(). Однако эти функции должны (и делать!) отклонять нестрочные.

Возможные прецеденты включают скрытие атрибутов от обычного точечного доступа и создание атрибутов в соответствии с внешними источниками данных (которые могут столкнуться с ключевыми словами Python). Таким образом, аргумент, кажется, просто не имеет оснований запрещать его.

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

Хотя dicts Python уже имеют некоторые строки только оптимизаций - они просто динамически адаптироваться к более общему и немного более медленному подходу, когда появится первая неквантовая строка.

1

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

  1. Вы хотите, чтобы объект имел атрибут, к которому нельзя получить доступ с помощью точечной нотации, например, чтобы защитить ее от наивного пользователя. (Quoting Guido: «Некоторые люди могут использовать это, чтобы скрыть состояние, которое они не хотят использовать, используя стандартную нотацию атрибутов (x.foo)». Конечно, продолжает он, «но это похоже на злоупотребление пространством имен для меня , и существует множество других способов управления таким состоянием. »)
  2. Вы хотите, чтобы имена атрибутов объекта соответствовали внешним данным, над которыми у вас нет контроля. Таким образом, вы должны быть в состоянии использовать все строки появляются во внешних данных, как имя атрибута, даже если она совпадает с Python зарезервированного слова или содержит пробела или тир и т.д.