Ініціалізувати рядкову змінну в Python: “” чи None?


75

Припустимо, у мене є клас з атрибутом екземпляра рядка . Чи слід ініціалізувати цей атрибут зі значенням "" чи " Ні" ? Чи все гаразд?

def __init__(self, mystr="")
   self.mystr = mystr

або

def __init__(self, mystr=None)
   self.mystr = mystr

Редагувати : Я вважав, що якщо я використовую "" як початкове значення, я " оголошую " змінну типу рядка . І тоді я не зможу призначити йому будь-який інший тип пізніше. Я правий?

Редагувати : Я думаю, тут важливо зазначити, що моя пропозиція була НЕПРАВИЛЬНОЮ. І немає проблем призначити інший тип змінної. Мені сподобався коментар С.Лотта : " Оскільки в Python нічого не" оголошено ", ви не думаєте про це правильно. "


6
Оскільки в Python нічого не "оголошено", ви не думаєте про це правильно.
S.Lott,

Відповіді:


82

Якщо відсутність значення має значення у вашій програмі (наприклад, необов’язкове значення), слід використовувати None. Це все одно його мета.

Якщо значення повинно бути надане абонентом __init__, я б рекомендував не ініціалізувати його.

Якщо "" має сенс як значення за замовчуванням, використовуйте його.

У Python тип виводиться із використання. Отже, ви можете змінити тип, просто призначивши значення іншого типу.

>>> x = None
>>> print type(x)
<type 'NoneType'>
>>> x = "text"
>>> print type(x)
<type 'str'>
>>> x = 42
>>> print type(x)
<type 'int'>

4
+1: Що означає None або ""? Вибір дизайну повністю залежить від того, яке значення є більш значущим.
S.Lott,

У наведеному вище прикладі "тип" x не змінився. Натомість у вас є 3 різні об’єкти різних типів: >>> x = None >>> id (x) 1461526688 >>> x = "text" >>> id (x) 2520221413080 >>> x = 42 >>> id (x) 1461692432 Натомість мітку x перемістили навколо трьох об’єктів.
DocOc

14

Жодне не використовується для позначення "не встановлено", тоді як будь-яке інше значення використовується для позначення значення "за замовчуванням".

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

Зверніть увагу, що не має значення, чи ваша змінна спочатку є рядком. Ви можете змінити його на будь-який інший тип / значення в будь-який інший момент.


12

Інший спосіб ініціалізації порожнього рядка - використання вбудованої str()функції без аргументів.

str (об'єкт = '')

Повернути рядок, що містить приємне для друку подання об'єкта.

...

Якщо аргумент не вказано, повертає порожній рядок, ''.

В оригінальному прикладі це виглядатиме так:

def __init__(self, mystr=str())
   self.mystr = mystr

Особисто я вважаю, що це краще передає ваші наміри.

Зауважте, до речі, що str()сам встановлює значення параметра за замовчуванням ''.


1
Для незмінних типів результат такий самий, як '', 0, False, (). Для змінних типів це навіть настільки погано, як [], {}, set () тощо, оскільки ця функція ініціалізації за замовчуванням викликається лише один раз, а результат використовується для _ init_ неодноразово ..
hynekcer

5

Це залежить. Якщо ви хочете розрізнити жоден параметр, який передано взагалі, і порожній рядок, переданий, ви можете використовувати None.


5

І те, і інше може бути добре, але я не думаю, що є однозначна відповідь.

  • Якщо ви хочете вказати, що значення не встановлено, порівняння з Noneкраще, ніж порівняння з "", оскільки ""може бути дійсним значенням,
  • Якщо ви просто хочете значення за замовчуванням, ""це, мабуть, краще, оскільки це насправді рядок, і ви можете викликати на нього рядкові методи. Якби ви пішли з Noneцим, це призвело б до винятків.
  • Якщо ви хочете вказати майбутнім розробникам, що тут потрібен рядок, ""можете допомогти в цьому.

Повна примітка:

Якщо у вас є цикл, скажіть:

def myfunc (self, mystr = ""):
    for other in self.strs:
        mystr = self.otherfunc (mystr, other)

тоді потенційний майбутній оптимізатор знав би, що strце завжди рядок. Якщо ви використовували None, то це може бути не рядок до першої ітерації, яка вимагала б розгортання циклу, щоб отримати ті самі ефекти. Хоча це не гіпотетично (цього багато в моєму компіляторі PHP), ви, звичайно, ніколи не повинні писати свій код, щоб це врахувати. Я просто подумав, що це може бути цікаво :)


Хороші коментарі, але вам слід уникати використання strв якості імені змінної, оскільки це затінить вбудовану str()функцію.
Даніель Роузман,

3

І те, і Noneінше - це нормально, хоча частіше зустрічається як домовленість - Noneозначає, що для необов’язкового параметра не було передано значення.

Там буде час , коли «» правильне значення по замовчуванням для використання - в моєму досвіді, ті часи зустрічаються рідше.


1

Оскільки None та "" є хибними, ви можете зробити і те, і інше. Див. 6.1. Перевірка цінності істини .

Редагувати

Щоб відповісти на питання у вашій редакції: Ні, ви можете призначити інший тип.

>>> a = ""
>>> type(a)
<type 'str'>
>>> a = 1
>>> type(a)
<type 'int'>

3
Ну, якщо він перевірить істинність, то він пропустить, що це ""може бути дійсним значенням. Краще, щоб він Noneзамість цього перевіряв наявність .
Paul Biggar,

Оскільки ми не знаємо, на що перевіряє ОП, ні ти, ні я не можемо судити, що для нього краще. До речі, чи вважали ви мою чітко позначену редакцію, яка відповідає редакції OP, коли ви проголосували проти моєї відповіді?

1

Для списків або диктів відповідь є більш чіткою, згідно з http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#default-parameter-values використовувати None як параметр за замовчуванням.

Але також для рядків, (порожній) рядок об'єкт інстанціюється під час виконання для параметра ключового слова.

Найчистіший спосіб - це, мабуть:

def myfunc(self, my_string=None):
    self.my_string = my_string or "" # or a if-else-branch, ...

4
Чому? Це 'робота параметра за замовчуванням, то чому це робити двічі? І чому б не чітко вказати, яке значення є типовим? Крім того , "" цілком очевидно заявляє, що функція очікує рядок, який вам Noneне повідомляє.
u0b34a0f6ae

1

У будь-якому випадку це нормально для python. Я особисто віддав би перевагу "". але знову ж таки, в будь-якому випадку це нормально

>>>x = None
>>>print(x)
None
>>>type(x)
<class 'NoneType'>
>>>x = "hello there"
>>>print(x)
hello there
>>>type(x)
<class 'str'>
>>> 
>>>x = ""
>>>print(x)

>>>type(x)
<class 'str'>
>>>x = "hello there"
>>>type(x)
<class 'str'>
>>>print(x)
hello there

1

Філософія Python має бути читабельною.
Ось чому є гарною практикою визначати свої атрибути, __init__()навіть якщо це необов’язково.
У цьому ж дусі ви повинні запитати себе, що зрозуміліше для кожного, хто читає ваш код. Насправді сам тип дає багато інформації про майбутнє використання вашої змінної. Так:

kind = None

Синтаксично правильний, але читач не знає багато чого. Це рядок, код як ціле число, список тощо?

kind_str = None
kind = ""

Обидва говорять трохи більше, перший має тип у назві, а другий у своїй декларації. Я пішов би за другим, акуратнішим.


0
empty_string = ""

if not empty_string:

    print "Empty string is not set"

=> Порожній рядок не встановлено

if empty_string is not None:
    print "Empty string is not None"

=> Порожній рядок - не None

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