Почему Python решил отказаться от постоянных ссылок? - PullRequest
25 голосов
/ 16 ноября 2010

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

У меня большая структура данных, и я хочувыставить его на другие модули, только для чтения.Единственный способ сделать это в Python - это глубокое копирование отдельных фрагментов, которые я хотел бы раскрыть - в моем случае это слишком дорого.

Я уверен, что это очень распространенная проблема, и кажется, чтопостоянная ссылка будет идеальным решением.Но я должен что-то упустить.Возможно, постоянные ссылки сложно реализовать в Python.Возможно, они не совсем делают то, что я думаю, что они делают.

Любые идеи будут оценены.


Хотя ответы полезны, я не видел ни одной причины, почемубыло бы трудно реализовать или не работать в Python.Я полагаю, что «непифония» также будет считаться веской причиной, но так ли это на самом деле?Python делает скремблирование частных переменных экземпляра (начиная с __), чтобы избежать случайных ошибок, и const, похоже, не слишком отличается по духу.


РЕДАКТИРОВАТЬ: я только что предложилочень скромная щедрость.Я ищу немного подробнее о том, почему Python оказался без констант.Я подозреваю, что причина в том, что это действительно трудно реализовать, чтобы работать идеально;Я хотел бы понять, почему это так сложно.

Ответы [ 5 ]

13 голосов
/ 16 ноября 2010

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

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

10 голосов
/ 20 ноября 2010

В PEP 351 Барри Варшава предложил протокол для «замораживания» любой изменяемой структуры данных, аналогично тому, как frozenset создает неизменный набор. Замороженные структуры данных могут быть хэшируемыми и поэтому могут использоваться в качестве ключей в словарях.

Предложение было обсуждено на python-dev , с критикой Раймона Хеттингера самым подробным.

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

8 голосов
/ 16 ноября 2010

Есть много вопросов о дизайне любого языка, ответ на большинство из которых «просто потому что». Совершенно очевидно, что подобные константы идут вразрез с идеологией Python.


Вы можете создать атрибут класса только для чтения, используя дескрипторы . Это не тривиально, но не очень сложно. Это работает так, что вы можете создавать свойства (вещи, которые выглядят как атрибуты, но вызывают метод при доступе), используя декоратор property; если вы сделаете getter, но не setter свойство, то вы получите атрибут только для чтения. Причина программирования метакласса состоит в том, что, поскольку __init__ получает полностью сформированный экземпляр класса, вы на самом деле не можете установить атрибуты того, что вы хотите на этом этапе! Вместо этого вы должны установить их при создании класса, что означает, что вам нужен метакласс.

Код от этого рецепта :

# simple read only attributes with meta-class programming

# method factory for an attribute get method
def getmethod(attrname):
    def _getmethod(self):
        return self.__readonly__[attrname]

    return _getmethod

class metaClass(type):
    def __new__(cls,classname,bases,classdict):
        readonly = classdict.get('__readonly__',{})
        for name,default in readonly.items():
            classdict[name] = property(getmethod(name))

        return type.__new__(cls,classname,bases,classdict)

class ROClass(object):
    __metaclass__ = metaClass
    __readonly__ = {'a':1,'b':'text'}


if __name__ == '__main__':
    def test1():
        t = ROClass()
        print t.a
        print t.b

    def test2():
        t = ROClass()
        t.a = 2

    test1()
1 голос
/ 21 ноября 2010

Для некоторых дополнительных размышлений, здесь есть похожий вопрос, касающийся Java:
Почему в Java нет функции Constant?

На вопрос, почему в Python есть решил против постоянных ссылок, думаю, полезно подумать о том, как они будут реализованы в языке.Должен ли Python иметь какое-то специальное объявление const для создания ссылок на переменные, которые нельзя изменить?Почему бы не позволить переменным быть объявленными как float / int / что-нибудь еще ... это, несомненно, поможет предотвратить ошибки программирования.Пока мы на этом, добавляем модификаторы класса и метода, такие как protected / private / public / etc.помог бы обеспечить проверку типа компиляции на предмет незаконного использования этих классов.... довольно скоро мы утратили красоту, простоту и элегантность Python, и мы пишем код на каком-то подонке C ++ / Java.

Python в настоящее время также передает всессылка.Это был бы какой-то особый способ передачи по ссылке, но пометить его как предотвращающий модификацию ... довольно особый случай (и, как указывает Дао в Python, просто "непифонический").

Как упоминалось ранее, без реального изменения языка этот тип поведения может быть реализован с помощью классов и дескрипторов.Это не может помешать модификации решительного хакера, но мы согласны на это.Python не обязательно решает отказаться от предоставления его в качестве включенного модуля («батарейки включены») - просто никогда не было достаточного спроса на него.

1 голос
/ 21 ноября 2010

В то время как один программист пишет код по обоюдному согласию, два программиста, работающие над одним и тем же кодом, редко бывают по обоюдному согласию.Более того, если они ценят не красоту кода, а его сроки или исследовательские фонды.

Для таких взрослых существует некоторая безопасность типов, обеспеченная Чертами .

* 1006 Enthought* Вы можете изучить черты Constant и ReadOnly.
...