Чи використовуєте ви шаблон get / set (у Python)?


82

Використання get / set, здається, є звичною практикою в Java (з різних причин), але я навряд чи бачу код Python, який використовує це.

Чому ви використовуєте або уникаєте методів get / set у Python?


Створюйте відповіді від усіх. Слід визнати, що це питання є відгалуженням цього одного 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

1
@ Nick D: Я маю на увазі, що це інтерпретована мова, яка заохочує читаність, а не продуктивність, тому в програмі буде набагато кращі місця для оптимізації.
wRAR

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

Ось що про це говорить Гвідо ван Россум у " Натхненниках програмування"

Що ви маєте на увазі під "боротьбою з мовою"?

Гвідо: Це зазвичай означає, що вони намагаються продовжувати свої звички, які добре працювали на іншій мові.

[...] Люди перетворять все на клас і перетворять кожен доступ на метод доступу,
де це дійсно не розумно робити в Python; у вас буде більше детального коду, який
важче налагоджувати і працює набагато повільніше. Ви знаєте вираз "Ви можете написати FORTRAN будь-якою мовою?" Ви також можете писати Java будь-якою мовою.


14

Ні, це непітонічно. Загальноприйнятим способом є використання звичайного атрибута даних і заміна тих, які потребують більш складної логіки get / set, властивостями.


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

7

Коротка відповідь на ваше запитання - ні, вам слід використовувати властивості, коли це потрібно. Райан Тамеоко дає довгу відповідь у своїй статті « Геттери / сетери / фуксори»

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


5

Ваше спостереження правильне. Це не звичайний стиль програмування на Python. Всі атрибути є загальнодоступними, тому ви просто отримуєте доступ (отримуєте, встановлюєте, видаляєте) до них, як і з атрибутами будь-якого об’єкта, що їх має (не лише класів чи екземплярів). Це легко зрозуміти, коли програмісти Java вивчають Python, тому що їх код Python виглядає як Java із використанням синтаксису Python!

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

Як цікаву демонстрацію, у програмуванні Core Python (глава 13, розділ 13.16) я запропонував приклад використання дескрипторів для зберігання атрибутів на диску, а не в пам'яті !! Так, це дивна форма постійного зберігання, але це дійсно показати вам приклад того , що можна!

Ось ще одна пов’язана публікація, яка також може вам виявитися корисною: Python: кілька властивостей, один сеттер / геттер


0

Я прийшов сюди за цією відповіддю (на жаль, не зміг). Але я знайшов роботу в іншому місці. Цей код нижче може бути альтернативою для отримання .
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
Це лише обхідний шлях . Використовуючи вищезазначену концепцію, ви могли б легко побудувати методологію get / set і в py.


-10

Наш учитель показав один приклад на уроці, пояснюючи, коли ми повинні використовувати функції доступу.

class Woman(Human):
    def getAge(self):
        if self.age > 30:
            return super().getAge() - 10
        else:
            return super().getAge()

Я не давав вам голосів проти, але я думав, що наберуся. Суть дискусії: "навіщо нам get () / set () для доступу до властивостей безпосередньо в Python". У Java є мовні ... особливості ..., які роблять це бажаним. У Python не так вже й багато.
Евері Пейн,

7
Окрім того, що насправді не відповідають на питання, приклад, використаний у цій відповіді, образливий. Твердження, що ваш вчитель ним користувався, не виправдовує його сексизму.
Touzen

Сумніваюся, це свідчить про сексизм, лише про вашу наївність. У поколінні моєї бабусі багато жінок жартували, що їх вік на кілька років молодший, ніж був насправді. До того ж це все одно не має нічого спільного з відповіддю.
Йохан Сноугуз,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.