Вы используете шаблон get / set (в Python)?

82

Использование get / set кажется обычной практикой в ​​Java (по разным причинам), но я почти не вижу кода Python, который использует это.

Почему вы используете или избегаете методов get / set в Python?

Roger Pate
источник
Отличные отзывы от всех. По общему признанию, этот вопрос является ответвлением этого вопроса stackoverflow.com/questions/1022970/… однако, похоже, что на меня напала толпа людей, смотрящих на него с точки зрения «J» -слова. Еще раз спасибо за восстановление моей веры в здравомыслие ...
Эйвери Пейн
1
Контекст важен, а здесь Python и Java просто разные. (Однако я удалил Python из заголовка, потому что мы используем для этого теги в SO.;)

Ответы:

59

Прикольная ссылка: Python - это не Java :)

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

мгв
источник
3
плюс сеттеры / геттеры увеличивают производительность, особенно в Python.
Ник Дандулакис
4
Это накладывает дополнительную нагрузку на конструктора классов, поскольку переменные экземпляра неявно становятся частью общедоступного API класса. Размещая класс, четко подумайте, к каким переменным экземпляра вы хотите получить доступ извне, а не к тем, которые на самом деле являются лишь частью реализации вашего класса. Перед внутренними реализациями поставьте перед ними знак "_". Это предупреждающий знак Python о том, что в случае изменения реализации эта переменная также может измениться или даже полностью исчезнуть. В противном случае вы обнаружите, что знания о реализации утекают из вашего класса, что затрудняет их изменение позже.
PaulMcG
8
@Nick D: Я не думаю, что аксессоры - подходящее место для оптимизации скорости в Python.
wRAR 05
1
@Nick D: Я имею в виду, что это интерпретируемый язык, который способствует удобочитаемости, а не производительности, поэтому в программе будет гораздо больше мест для оптимизации.
wRAR 05
2
@Paul: это не внутренний атрибут, если он не назван с одним или двумя ведущими символами подчеркивания (обычно предпочтительнее первая форма, поскольку последняя искажает необычное имя Python). Если вы не хотите писать документы и эта проблема вас беспокоит, просто используйте _name по умолчанию для всех атрибутов экземпляра.
113

В python вы можете просто получить доступ к атрибуту напрямую, потому что он общедоступен:

class MyClass:

    def __init__(self):
        self.my_attribute = 0  

my_object = MyClass()
my_object.my_attribute = 1 # etc.

Если вы хотите что-то сделать при доступе или изменении атрибута, вы можете использовать свойства :

class MyClass:

    def __init__(self):
        self._my_attribute = 0

    @property
    def my_attribute(self):
        # Do something if you want
        return self._my_attribute

    @my_attribute.setter
    def my_attribute(self, value):
        # Do something if you want
        self._my_attribute = value

Важно отметить, что код клиента остается прежним.

оборота блокелей
источник
30

Вот что об этом говорит Гвидо ван Россум в своей книге «Masterminds of Programming».

Что вы имеете в виду под «борьбой с языком»?

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

[...] Люди превратят все в класс и превратят каждый доступ в метод доступа,
хотя это действительно неразумно в Python; у вас будет более подробный код, который будет
труднее отлаживать и который будет работать намного медленнее. Вы знаете выражение «Фортран можно писать на любом языке»? Вы также можете писать Java на любом языке.

оборота Ник Дандулакис
источник
14

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

Макс Шавабке
источник
13
+1: «Мы все здесь взрослые». Код виден. "private" и "getter / setter" не создают никакого значения, когда можно увидеть весь код.
S.Lott
7

Короткий ответ на ваш вопрос: нет, при необходимости вы должны использовать свойства. Райан Тамиоко дает подробный ответ в своей статье Getters / Setters / Fuxors.

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

Шейн С. Мейсон
источник
5

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

Я определенно согласен со всеми предыдущими плакатами, особенно ссылкой @ Maximiliano на знаменитую статью Филиппа и предположением @ Max о том, что для чего-то более сложного, чем стандартный способ установки (и получения) атрибутов класса и экземпляра, является использование свойств (или дескрипторов, чтобы обобщить еще больше) для настройки получения и настройки атрибутов! (Это включает в себя возможность добавлять свои собственные индивидуализированные версии частной, защищенной, дружеской или любой другой политики, которую вы хотите, если вы хотите чего-то другого, кроме общедоступной.)

В качестве интересной демонстрации в Core Python Programming (глава 13, раздел 13.16) я придумал пример использования дескрипторов для хранения атрибутов на диске, а не в памяти !! Да, это странная форма постоянного хранения, но это действительно показать вам пример того , что можно!

Вот еще один связанный пост, который также может оказаться полезным: Python: несколько свойств, один установщик / получатель

мин
источник
0

Я пришел сюда за этим ответом (к сожалению, не смог). Но я нашел работу в другом месте. Этот приведенный ниже код может быть альтернативой для get .
class get_var_lis: def __init__(self): pass def __call__(self): return [2,3,4] def __iter__(self): return iter([2,3,4]) some_other_var = get_var_lis
Это просто обходной путь . Используя вышеупомянутую концепцию, вы можете легко создать методологию получения / установки и в py.

Юнус
источник
-10

Наш учитель показал в классе один пример, объясняющий, когда нам следует использовать функции доступа.

class Woman(Human):
    def getAge(self):
        if self.age > 30:
            return super().getAge() - 10
        else:
            return super().getAge()
sjhstone
источник
Я не ставил вам отрицательных голосов, но я подумал, что присоединюсь к вам. Суть обсуждения заключается в том, «зачем нам get () / set () для доступа к свойствам непосредственно в Python». В Java есть языковые ... особенности ... которые делают это желательным. В Python не так много.
Эйвери Пейн,
7
Помимо того, что на самом деле я не ответил на вопрос, пример, использованный в этом ответе, является оскорбительным. Утверждение, что ваш учитель использовал его, не оправдывает его сексизм.
Touzen
Я сомневаюсь, что это показывает сексизм, просто вашу наивность. В поколении моей бабушки многие женщины шутили, что их возраст был на несколько лет моложе, чем был на самом деле. К тому же это все равно не имеет отношения к ответу.
Johan Snowgoose