Що таке значення "None"?


130

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

Я хочу знати , що Noneзначення є і те , що ви використовуєте це?

А також я не розумію цієї частини книги:

Присвоєння значення Noneзмінної - це один із способів відновити її до початкового, порожнього стану.

Що це означає?

Відповіді були чудовими, хоча я не зрозумів більшість відповідей через мої низькі знання про комп'ютерний світ (я не дізнався про заняття, предмети тощо). Що означає це речення?

Присвоєння значення Noneзмінної - це один із способів відновити її до початкового, порожнього стану.

Фінал:

Нарешті я отримав свою відповідь, шукаючи різні відповіді. Я повинен цінувати всіх людей, які приділяли свій час, щоб допомогти мені (особливо Мартійн Пітерс і DSM), і я хотів би, щоб я міг вибрати всі відповіді як найкращі, але вибір обмежений однією. Усі відповіді були чудовими.


39
Ця книга не надто корисна; Noneне є порожнім станом за умовчанням для змінних.
Martijn Pieters

PHP вгорі моєї голови є єдиною мовою, нульове значення якої еквівалентно порожньому стану за замовчуванням для змінної. Тепер мені цікаво, які інші мови роблять це.
kojiro

@kojiro perl, хоча жоден з операторів рівності не радий порівнянню undef. також, мабуть, JavaScript, хоча він має nullі undefined.
Eevee

За замовчуванням значення змінної @kojiro javascript є undefined, якщо її залишити неініціалізованою.
thefourtheye

Право, що відрізняється від nullмоменту, якого я не можу зробити @MartijnPieters у своїй відповіді.
kojiro

Відповіді:


99

Відповідь Мартійна пояснює, що Noneє в Python, і правильно стверджує, що книга вводить в оману. Оскільки програмісти Python, як правило, ніколи не скажуть

Присвоєння значення Noneзмінної - це один із способів відновити її до початкового, порожнього стану.

важко пояснити, що означає Бріггс, таким чином, що має сенс і пояснює, чому тут ніхто не здається задоволеним. Одна аналогія, яка може допомогти:

У Python назви змінних схожі на наклейки, розміщені на об'єктах. Кожна наклейка має унікальну назву, написану на ній, і вона може бути лише на одному об’єкті одночасно, але ви можете поставити більше одного наклейки на один і той же об’єкт, якщо хочете. Коли пишеш

F = "fork"

ви ставите наклейку "F" на рядовий об'єкт "fork". Якщо ви тоді пишете

F = None

ви переміщаєте наклейку на Noneпредмет.

Те, що Бріггс просить вас уявити, - це те, що ви не написали наклейку "F", на наклейці вже була Fнаклейка None, і все, що ви робили, - це перенести її, з Noneна "fork". Тож, коли ви вводите F = None, ви "скидаєте [відтінок] до початкового, порожнього стану", якщо ми вирішили трактувати Noneяк значення empty state.

Я бачу, на що він потрапляє, але це поганий спосіб поглянути на це. Якщо ви запускаєте Python і набираєте текст print(F), ви бачите

>>> print(F)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'F' is not defined

а це NameErrorозначає, що Python не розпізнає ім'я F, оскільки такої наклейки немає . Якщо Бріггс мав рацію і F = Noneскидає Fсвій початковий стан, то він зараз повинен бути там, і ми повинні бачити

>>> print(F)
None

як ми робимо після того, як наберемо F = Noneта надінемо наклейку None.


Отже, це все, що відбувається. Насправді Python постачається з деякими наклейками, які вже прикріплені до об'єктів (вбудовані імена), але для інших вам доведеться писати себе такими рядками, як F = "fork"і A = 2і c17 = 3.14, а потім ви можете наклеїти їх на інші об’єкти пізніше (наприклад, F = 10або F = Noneвсе одно .)

Бріггс робить вигляд, що всі можливі наклейки, які ви хочете написати, вже були приклеєні до Noneоб'єкта.


1
Вибачте, але що ви маєте на увазі під Бріггсом? Ви посилаєтесь на автора цієї книги? тому що його звуть Джейсон Р. Бріггс.
The_Diver

@The_Diver: так, це він.
DSM

Де я можу знайти більше інформації про вбудовані імена Python? Дякую.
The_Diver

3
Це чудове пояснення для непрограміста. Велике спасибі!
Крістіна

67

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

У даному сеансі інтерпретатора Python є лише одна копія цього об'єкта.

Якщо ви пишете функцію, а ця функція не використовує явного returnоператора, Noneзамість цього повертається. Таким чином, програмування з функціями значно спрощується; функція завжди щось повертає , навіть якщо це лише теNone об'єкт.

Ви можете перевірити це явно:

if foo is None:
    # foo is set to None

if bar is not None:
    # bar is set to something *other* than None

Іншим способом є надання додатковим параметрам функцій за замовчуванням "порожній":

def spam(foo=None):
    if foo is not None:
        # foo was specified, do something clever!

Функція spam()має необов'язковий аргумент; якщо ви зателефонували, spam()не вказуючи його, йому надається значення за замовчуванням None, що полегшує виявлення, викликали функцію з аргументом чи ні.

Інші мови мають подібні поняття. SQL має NULL; У JavaScript є undefined і null т.д.

Зауважте, що в Python змінні існують завдяки використанню. Вам не потрібно спочатку оголошувати змінну, тому в Python немає дійсно порожніх змінних. Встановити змінну у Noneце не те саме, що встановити її за замовчуванням порожнє значення; Noneце також значення, хоч і таке, яке часто використовується для сигналізації порожнечі. Книга, яку ви читаєте, в цьому питанні вводить в оману.


1
Я думаю, що семантика порожнечі відрізняється від невизначеності . Тож я не впевнений, що аналоги JavaScript та SQL уточнюють - вони можуть сплутати проблему. У JavaScript є undefined і null .
kojiro

@kojiro: undefined- це об'єкт у JavaScript, і ви можете використовувати цей об'єкт явно так само, як і Noneв Python. Це сигнальний об’єкт, має майже те саме значення.
Мартійн Пітерс

@kojiro: SQL - це не мова програмування, але NULL все-таки є те, що може бути призначено і перевірено на явну думку.
Martijn Pieters

5
@MartijnPieters: SQL - мова програмування, просто дуже конкретна мета, декларативна.
danielkza

3
@daniel: тим більше, що SQL кваліфікується як мова програмування, тривала дискусія ... Про цікаві аспекти див. stackoverflow.com/questions/900055/… .
Martijn Pieters

23

Про це має сказати документація PythonNone :

Єдине значення типів.NoneType. Жоден часто не використовується для відображення відсутності значення, як коли аргументи за замовчуванням не передаються функції.

Змінено у версії 2.4: Призначення до None є незаконним і викликає SyntaxError.

Примітка. Імена None і налагодження не можуть бути перепризначені (присвоєння їм, навіть як ім'я атрибута, піднімають SyntaxError), тому їх можна вважати "справжніми" константами.

  1. Підтвердимо тип Noneпершого

    print type(None)
    print None.__class__

    Вихідні дані

    <type 'NoneType'>
    <type 'NoneType'>

В основному, NoneTypeце такий тип даних, як int,float т. Д. Ви можете переглянути список типів за замовчуванням, доступний у Python в 8.15. type - Імена для вбудованих типів .

  1. І, None є екземпляром NoneTypeкласу. Тож ми можемо захотіти створити примірники Noneсебе. Давайте спробуємо це

    print types.IntType()
    print types.NoneType()

    Вихідні дані

    0
    TypeError: cannot create 'NoneType' instances

Так ясно, створити не можна NoneType екземпляри. Нам не потрібно турбуватися про унікальність цінності None.

  1. Давайте перевіримо, як ми реалізували None внутрішньо.

    print dir(None)

    Вихідні дані

    ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', 
     '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__',
     '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

За винятком __setattr__ , що всі інші є атрибутами лише для читання. Отже, ми не можемо змінити атрибути None.

  1. Спробуємо та додамо нові атрибути None

    setattr(types.NoneType, 'somefield', 'somevalue')
    setattr(None, 'somefield', 'somevalue')
    None.somefield = 'somevalue'

    Вихідні дані

    TypeError: can't set attributes of built-in/extension type 'NoneType'
    AttributeError: 'NoneType' object has no attribute 'somefield'
    AttributeError: 'NoneType' object has no attribute 'somefield'

Вищезазначені твердження створюють відповідно ці повідомлення про помилки. Це означає, що ми не можемо динамічно створювати атрибути на Noneекземплярі.

  1. Давайте перевіримо, що відбувається, коли ми щось призначимо None. Згідно з документацією, вона повинна кинути а SyntaxError. Це означає, якщо ми щось призначимоNone , програма взагалі не буде виконуватися.

    None = 1

    Вихідні дані

    SyntaxError: cannot assign to None

Ми це встановили

  1. None є екземпляром NoneType
  2. None не може мати нових атрибутів
  3. Існуючі атрибути None не можуть бути змінені.
  4. Ми не можемо створити інші екземпляри NoneType
  5. Ми навіть не можемо змінити посилання None, присвоївши йому значення.

Отже, як зазначено в документації, Noneсправді можна розглядати якtrue constant .

Щасливі знання None:)


Дуже дуже цікаво !! сумніваюся, для чого користь __setattr__для None
Grijesh Chauhan

9

Книга, на яку ви посилаєтесь, явно намагається значно спростити значення None. Змінні Python не мають початкового, порожнього стану - змінні Python пов'язані (лише), коли вони визначені . Ви не можете створити змінну Python, не давши їй значення.

>>> print(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> def test(x):
...   print(x)
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test() takes exactly 1 argument (0 given)
>>> def test():
...   print(x)
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test
NameError: global name 'x' is not defined

але іноді ви хочете, щоб функція означала різні речі залежно від того, визначена чи ні змінна. Ви можете створити аргумент зі значенням за замовчуванням None:

>>> def test(x=None):
...   if x is None:
...     print('no x here')
...   else:
...     print(x)
... 
>>> test()
no x here
>>> test('x!')
x!

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

>>> def test(x=-1):
...   if x == -1:
...     print('no x here')
...   else:
...     print(x)
... 
>>> test()
no x here
>>> test('x!')
x!

… Але наявність Noneу нас дає дві переваги:

  1. Нам не потрібно вибирати особливе значення -1, таке, чий сенс незрозумілий, і
  2. Нашу функцію насправді потрібно обробляти -1як звичайний вхід.
>>> test(-1)
no x here

ой!

Таким чином, книга трохи вводить в оману в основному у використанні слова скидання - присвоєння Noneімені є сигналом для програміста, що це значення не використовується або що функція повинна вести себе за замовчуванням, але для скидання значення до початкового, невизначеного стану, ви повинні використовувати delключове слово:

>>> x = 3
>>> x
3
>>> del x
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

5

Інші відповіді вже прекрасно пояснили значення None . Однак я все ж хотів би на цьому прикласти більше світла, використовуючи приклад.

Приклад:

def extendList(val, list=[]):
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3

Тепер спробуйте відгадати вихід із зазначеного вище списку. Що ж, відповідь дивно, як нижче:

list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']

Але чому?

Багато хто помилково очікує, що list1 дорівнює [10], а list3 дорівнює ['a'] , думаючи, що аргумент списку буде встановлено за замовчуванням [] щоразу, коли викликається розширення списку.

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

таким чином list1 та list3 працюють у тому ж списку за замовчуванням, тоді як list2 працює в окремому створеному списку (передаючи власний порожній список як значення для параметра списку).


"Ні" рятівник: (Змініть приклад вище, щоб створити бажану поведінку)

def extendList(val, list=None):
    if list is None:
       list = []
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3

З цією переглянутою реалізацією результат буде:

list1 = [10]
list2 = [123]
list3 = ['a']

Примітка - Приклад кредиту для toptal.com


3

Жоден об'єкт не є однотонним (мається на увазі, що існує лише один None), який використовується в багатьох місцях мови та бібліотеки для відображення відсутності якогось іншого значення.


Наприклад:
якщо dце словник, d.get(k)повернеться, d[k]якщо він існує, але Noneякщо dнемає ключа k.

Прочитайте цю інформацію з чудового блогу: http://python-history.blogspot.in/


3

Все це є гарними відповідями, але я думаю, що є більше, щоб пояснити, чому None це корисно.

Уявіть, що ви збираєте RSVP на весілля. Ви хочете записати, чи буде присутня кожна людина. Якщо вони відвідують, ви встановлюєте person.attending = True. Якщо вони не відвідують вас, встановіть person.attending = False. Якщо ви не отримали жодного RSVP, то person.attending = None. Таким чином ви можете розрізняти відсутність інформації - None- і негативну відповідь.


1

Я люблю приклади коду (як і фрукти), тому дозвольте вам показати

apple = "apple"
print(apple)
>>> apple
apple = None
print(apple)
>>> None

Жоден нічого не означає, він не має значення.

Жоден не оцінює "Неправдивий".


8
print(None)печать .. None. Це робить НЕ , як ви не пропонуєте, друк нічого.
Martijn Pieters

REPL нічого не показує, Noneякщо це результат останнього виразу. (що корисно для функцій, не призначених для повернення значення.)
Eevee

Так, моя помилка, я використовував IDLE, і я припускав, що він друкує змінні, мабуть, він використовує repl. В даний час я використовую SO для вдосконалення власних навичок читання та розуміння пітона / JavaScript / коду, тому я роблю деякі помилки :(
Azeirah

2
IDLE, як і запит інтерактивного інтерпретатора Python, явно приховує, None якщо це результат виразу, здебільшого, щоб не захаращувати результат.
Martijn Pieters

-5
largest=none
smallest =none 
While True :
          num =raw_input ('enter a number ') 
          if num =="done ": break 
          try :
           inp =int (inp) 
          except:
              Print'Invalid input' 
           if largest is none :
               largest=inp
           elif inp>largest:
                largest =none 
           print 'maximum', largest

          if smallest is none:
               smallest =none
          elif inp<smallest :
               smallest =inp
          print 'minimum', smallest 

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