Class key error

The g++ compiler complains with this error when I declare a friend thusly: friend MyClass; instead of friend class MyClass; Why should the class keyword be required? (the Borland C++ compiler,...

The g++ compiler complains with this error when I declare a friend thusly:

friend MyClass;

instead of

friend class MyClass;

Why should the class keyword be required?
(the Borland C++ compiler, BTW, does not require it.)

Couldn’t the compiler simply look-up MyClass in the symbol table and tell it was declared as a class? (it is obviously doing the look-up anyway because it complains when MyClass it not declared)

It is not like it is making a forward declaration of the class: I still have to have either declared the class above or at least have forward declared it.

It would make sense to me (would be great actually) if

friend class MyClass;

makes a forward declaration if needed, otherwise it just seems like syntactic salt to me.

I have been merrily using friend statements without the class or struct keyword with no compiler complaints for almost 20 years.
Is this something fairly new?

asked Mar 18, 2009 at 4:18

Roger Nelson's user avatar

Roger NelsonRoger Nelson

1,8622 gold badges15 silver badges21 bronze badges

2

I was surprised about this (and as a result deleted a previous incorrect answer). The C++03 standard says in 11.4:

An elaborated-type-specifier shall be used in a friend declaration for a class.

Then to make sure there’s no misunderstanding, it footnotes that with:

The class-key of the elaborated-type-specifier is required.

GCC is the only compiler that I have that complains about the missing class-key, but it looks like other compilers are letting us get away with something non-standard…

Now as for the rationale — you’d have to ask someone who knows more about compilers (or standards) than I do.

answered Mar 18, 2009 at 5:58

Michael Burr's user avatar

Michael BurrMichael Burr

329k50 gold badges528 silver badges755 bronze badges

2

To the point of your question, because it is the way ISO/IEC 14882:2003 specifies it (section 7.1.4). The friend construct is essentially specified as:

friend <declaration>

where <declaration> is the valid declaration of a class, struct, template, or function.

Thus,

MyClass;

is not a valid declaration, whereas:

class MyClass;

or:

struct MyClass;

are.

Idem for, correspondingly:

friend class MyClass;

or

friend struct MyClass;

answered Mar 18, 2009 at 4:20

vladr's user avatar

2

Ситуация: мы пишем программу для зоопарка, в которой учитывается всё — имена, возраст животных, какой они породы и так далее. Чтобы это хранить, мы используем словари. Словарь состоит из пар «ключ — значение». И вот мы подходим к интерактивному фрагменту, когда программа сообщает пользователю, как зовут любимую лошадь в зоопарке:

names = {'кошка': 'Кузя', 'собака': 'Жук', 'мышь': 'Рататуй', 'конь': 'Спирит'}
# дальше идёт остальной код
# который важен для работы программы
# … 
# и вот мы возвращаемся к словарю
print('Нашу любимую лошадь зовут ' + names['лошадь'])

Но при запуске код почему-то выдаёт такую ошибку:

❌ KeyError: 'лошадь'

Что это значит: питон взял наш словарь с именами не смог найти в нём ключ «лошадь». А раз что-то не получается сделать, интерпретатор сразу выводит ошибку и сообщает, что проблема в ключе.

Когда встречается: когда мы используем ключ, которого нет в словаре. 

Что делать с ошибкой KeyError

Эта ошибка случается по двум причинам:

  1. Мы используем неправильный ключ, которого нет в словаре.
  2. Мы перепутали словари и пытаемся использовать ключ от одного словаря в другом.

В обоих случаях для исправления достаточно посмотреть, какие ключи лежат в нужном нам словаре, и использовать именно их. 

В нашем коде ошибка такая: у нас есть ключ «конь», но нет ключа «лошадь». Так как править ключ в словаре — это неверный подход (потому что словарь может использоваться и в других местах), нам нужно заменить в команде вывода ключ на верный:

names = {'кошка': 'Кузя', 'собака': 'Жук', 'мышь': 'Рататуй', 'конь': 'Спирит'}
# дальше идёт остальной код
# который тоже важен для работы программы
# … 
# и вот мы возвращаемся к словарю
print('Нашу любимую лошадь зовут ' + names['конь'])

Вёрстка:

Кирилл Климентьев

Parent:
IndexError

Возникает, когда указанный ключ не найден. Это подкласс IndexError .

h = {"foo" => :bar}
h.fetch("foo") 
h.fetch("baz") 

Общественный класс Методы

новое (сообщение = ноль, получатель: ноль, ключ: ноль) → key_error Показать источник

static VALUE
key_err_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE options;

    rb_call_super(rb_scan_args(argc, argv, "01:", NULL, &options), argv);

    if (!NIL_P(options)) {
        ID keywords[2];
        VALUE values[numberof(keywords)];
        int i;
        keywords[0] = id_receiver;
        keywords[1] = id_key;
        rb_get_kwargs(options, keywords, 0, numberof(values), values);
        for (i = 0; i < numberof(values); ++i) {
            if (values[i] != Qundef) {
                rb_ivar_set(self, keywords[i], values[i]);
            }
        }
    }

    return self;
}

KeyError новое исключение KeyError с указанным сообщением, получателем и ключом.

Методы публичной медицины

static VALUE
key_err_key(VALUE self)
{
    VALUE key;

    key = rb_ivar_lookup(self, id_key, Qundef);
    if (key != Qundef) return key;
    rb_raise(rb_eArgError, "no key is available");
}

Вернуть ключ, вызвавший это исключение KeyError .

static VALUE
key_err_receiver(VALUE self)
{
    VALUE recv;

    recv = rb_ivar_lookup(self, id_receiver, Qundef);
    if (recv != Qundef) return recv;
    rb_raise(rb_eArgError, "no receiver is available");
}

Вернуть получателя, связанного с этим исключением KeyError .


Ruby

3.1

  • Examples

  • Parameters

  • Keywords

  • class LoadError

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

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

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

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

Давайте рассмотрим пример, чтобы понять, как мы можем использовать словарь (dict) в Python:

 
# A null Dictionary  
Dict = {}  
print("Null dict: ")  
print(Dict)  
  
# A Dictionary using Integers  
Dict = {1: 'Hill', 2: 'And', 3: 'Mountin'}  
print("nDictionary with the use of Integers: ")  
print(Dict)  
  
# A Dictionary using Mixed keys  
Dict = {'Name': 'John', 1: [17, 43, 22, 51]}  
print("nDictionary with the use of Mixed Keys: ")  
print(Dict)  
  
# A Dictionary using the dict() method  
Dict = dict({1: 'London', 2: 'America', 3:'France'})  
print("nDictionary with the use of dict(): ")  
print(Dict)  
  
# A Dictionary having each item as a Pair  
Dict = dict([(1, 'Hello'),(2, 'World')])  
print("nDictionary with each item as a pair: ")  
print(Dict) 

Вывод:

Null dict:  
{} 
nDictionary with the use of Integers:  
{1: 'Hill', 2: 'And', 3: 'Mountin'} 
nDictionary with the use of Mixed Keys:  
{'Name': 'John', 1: [17, 43, 22, 51]} 
nDictionary with the use of dict():  
{1: 'London', 2: 'America', 3: 'France'} 
nDictionary with each item as a pair:  
{1: 'Hello', 2: 'World'} 

Keyerror в Python

Когда мы пытаемся получить доступ к ключу из несуществующего dict, Python вызывает ошибку Keyerror. Это встроенный класс исключений, созданный несколькими модулями, которые взаимодействуют с dicts или объектами, содержащими пары ключ-значение.

Теперь мы знаем, что такое словарь Python и как он работает. Давайте посмотрим, что определяет Keyerror. Python вызывает Keyerror всякий раз, когда мы хотим получить доступ к ключу, которого нет в словаре Python.

Логика сопоставления – это структура данных, которая связывает один фрагмент данных с другими важными данными. В результате, когда к сопоставлению обращаются, но не находят, возникает ошибка. Это похоже на ошибку поиска, где семантическая ошибка заключается в том, что искомого ключа нет в его памяти.

Давайте рассмотрим пример, чтобы понять, как мы можем увидеть Keyerror в Python. Берем ключи A, B, C и D, у которых D нет в словаре Python. Хотя оставшиеся ключи, присутствующие в словаре, показывают вывод правильно, а D показывает ошибку ключа.

 
# Check the Keyerror 
ages={'A':45,'B':51,'C':67} 
print(ages['A']) 
print(ages['B']) 
print(ages['C']) 
print(ages['D']) 

Вывод:

45 
51 
67 
Traceback(most recent call last): 
File "", line 6, in  
KeyError: 'D' 

Механизм обработки ключевой ошибки в Python

Любой, кто сталкивается с ошибкой Keyerror, может с ней справиться. Он может проверять все возможные входные данные для конкретной программы и правильно управлять любыми рискованными входами. Когда мы получаем KeyError, есть несколько обычных методов борьбы с ним. Кроме того, некоторые методы могут использоваться для обработки механизма ошибки ключа.

Обычное решение: метод .get()

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

Например, если мы получаем ошибку из словаря в нашем собственном коде, мы можем использовать метод .get() для получения либо указанного ключа, либо значения по умолчанию.

Давайте рассмотрим пример, чтобы понять, как мы можем обработать механизм ошибки ключа в Python:

 
# List of vehicles and their prices.  
vehicles = {"Car=": 300000, "Byke": 115000, "Bus": 250000} 
vehicle = input("Get price for: ") 
vehicle1 = vehicles.get(vehicle) 
if vehicle1: 
    print("{vehicle} is {vehicle1} rupees.") 
else: 
    print("{vehicle}'s cost is unknown.") 

Вывод:

Get price for: Car 
Car is 300000 rupees. 

Общее решение для keyerror: метод try-except

Общий подход заключается в использовании блока try-except для решения таких проблем путем создания соответствующего кода и предоставления решения для резервного копирования.

Давайте рассмотрим пример, чтобы понять, как мы можем применить общее решение для keyerror:

 
# Creating a dictionary to store items and prices 
items = {"Pen" : "12", "Book" : "45", "Pencil" : "10"} 
try: 
  print(items["Book"]) 
except: 
  print("The items does not contain a record for this key.")   

Вывод:

45 

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

 
# Creating a dictionary to store items and prices 
items = {"Pen" : "12", "Book" : "45", "Pencil" : "10"} 
try: 
  print(items["Notebook"]) 
except: 
  print("The items does not contain a record for this key.")  

Вывод:

The items does not contain a record for this key. 

Заключение

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

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

Если проблема заключается в поиске ключа словаря в нашем собственном коде, мы можем использовать более безопасную функцию .get() с возвращаемым значением по умолчанию вместо запроса ключа непосредственно в словаре. Если наш код не вызывает проблемы, блок try-except – лучший вариант для регулирования потока нашего кода.

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

Изучаю Python вместе с вами, читаю, собираю и записываю информацию опытных программистов.

Исключения Python KeyError и как их обработать

Исключение PythonKeyError — распространенное исключение, с которым сталкиваются новички. Знание, почемуKeyError может быть повышено, и некоторые решения, позволяющие предотвратить остановку вашей программы, — важные шаги к совершенствованию как программиста Python.

К концу этого руководства вы будете знать:

  • Что обычно означает PythonKeyError

  • Где еще вы могли бы увидетьKeyError в стандартной библиотеке

  • Как обращаться сKeyError, когда вы его видите

Что обычно означаетKeyError в Python

PythonKeyErrorexception — это то, что возникает, когда вы пытаетесь получить доступ к ключу, которого нет вdictionary (dict).

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

PythonKeyError является типом исключенияLookupError и означает, что возникла проблема с получением ключа, который вы искали. Когда вы видитеKeyError, семантическое значение состоит в том, что искомый ключ не может быть найден.

В приведенном ниже примере вы можете увидеть словарь (ages) с возрастом трех человек. Когда вы пытаетесь получить доступ к ключу, которого нет в словаре, возникаетKeyError:

>>>

>>> ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
>>> ages['Michael']
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'Michael'

Здесь попытка доступа к ключу'Michael' в словареages приводит к подъемуKeyError. В нижней части трассировки вы получите соответствующую информацию:

  • Тот факт, что aKeyError был повышен

  • Ключ, который не удалось найти,'Michael'

Строка от последней к последней говорит вам, какая строка вызвала исключение. Эта информация более полезна, когда вы выполняете код Python из файла.

Note: Когда в Python возникает исключение, это делается с помощьюtraceback. Трассировка предоставляет вам всю необходимую информацию, чтобы определить, почему возникло исключение и что его вызвало.

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

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

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5 print(f'{person} is {ages[person]} years old.')

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

Повторяя неудачный пример выше, мы получаем еще одну трассировку, на этот раз с информацией о строке в файле, из которой возникаетKeyError:

$ python ages.py
Get age for: Michael
Traceback (most recent call last):
File "ages.py", line 4, in 
  print(f'{person} is {ages[person]} years old.')
KeyError: 'Michael'

Программа не работает, когда вы даете ключ, которого нет в словаре. Здесь последние несколько строк трассировки указывают на проблему. File "ages.py", line 4, in <module> сообщает вам, в какой строке какого файла возникло исключениеKeyError. Тогда вам показывают эту линию. Наконец, исключениеKeyError предоставляет недостающий ключ.

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

Note: Как и в примере выше, большинство других примеров в этом руководстве используютf-strings, которые были введены в Python 3.6.

Где еще вы могли бы увидеть PythonKeyError в стандартной библиотеке

В подавляющем большинстве случаев вызывается PythonKeyError, потому что ключ не найден в словаре или подклассе словаря (например,os.environ).

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

В следующем примере вы можете увидеть использование классаzipfile.ZipFile для извлечения информации о ZIP-архиве с помощью.getinfo():

>>>

>>> from zipfile import ZipFile
>>> zip_file = ZipFile('the_zip_file.zip')
>>> zip_file.getinfo('something')
Traceback (most recent call last):
File "", line 1, in 
File "/path/to/python/installation/zipfile.py", line 1304, in getinfo
  'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'something' in the archive"

Это не похоже на поиск по словарю. Вместо этого это вызовzipfile.ZipFile.getinfo() вызывает исключение.

Трассировка также выглядит немного иначе, поскольку предоставляется немного больше информации, чем просто отсутствующий ключ:KeyError: "There is no item named 'something' in the archive".

И последнее, на что следует обратить внимание, это то, что строки, которая поднялаKeyError, нет в вашем коде. Он находится в кодеzipfile, но предыдущие строки трассировки указывают, какие строки в вашем коде вызвали проблему.

Когда вам нужно поднять PythonKeyError в собственном коде

Бывают случаи, когдаyou to raise является исключением PythonKeyError в вашем собственном коде. Это можно сделать, используя ключевое словоraise и вызывая исключениеKeyError:

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

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

Как обращаться с PythonKeyError, когда вы его видите

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

Обычное решение:.get()

ЕслиKeyError возникает из-за неудачного поиска ключа словаря в вашем собственном коде, вы можете использовать.get() для возврата либо значения, найденного в указанном ключе, либо значения по умолчанию.

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

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5 age = ages.get(person)
 6
 7 if age:
 8     print(f'{person} is {age} years old.')
 9 else:
10     print(f"{person}'s age is unknown.")

Здесь в строке 5 показано, как можно получить значение возраста изages с помощью.get(). Это приведет к тому, что переменнаяage будет иметь значение возраста, найденное в словаре для предоставленного ключа, или значение по умолчанию,None в этом случае.

На этот раз вы не получите исключениеKeyError из-за использования более безопасного метода.get() для получения возраста, а не попытки получить доступ к ключу напрямую:

$ python ages.py
Get age for: Michael
Michael's age is unknown.

В приведенном выше примере выполненияKeyError больше не возникает, если указан неверный ключ. Ключ'Michael' не найден в словаре, но, используя.get(), мы получаем возвращаемыйNone, а не поднятыйKeyError.

Переменнаяage будет иметь либо возраст человека, найденный в словаре, либо значение по умолчанию (по умолчаниюNone). Вы также можете указать другое значение по умолчанию в вызове.get(), передав второй аргумент.

Это строка 5 из приведенного выше примера с другим возрастом по умолчанию, указанным с помощью.get():

age = ages.get(person, 0)

Здесь вместо'Michael', возвращающегоNone, он вернет0, потому что ключ не найден, а возвращаемое значение по умолчанию теперь0.

Редкое решение: проверка на наличие ключей

Есть моменты, когда вам нужно определить наличие ключа в словаре. В этих случаях использование.get() может не дать вам правильную информацию. ПолучениеNone, возвращенного из вызова.get(), может означать, что ключ не был найден или что значение, найденное для ключа в словаре, на самом делеNone.

Со словарем или подобным словарю объектом вы можете использовать операторin, чтобы определить, присутствует ли ключ в отображении. Этот оператор вернет логическое (True илиFalse) значение, указывающее, найден ли ключ в словаре.

В этом примере вы получаете словарьresponse в результате вызова API. Этот ответ может иметь значение ключаerror, определенное в ответе, что указывает на то, что ответ находится в состоянии ошибки:

 1 # parse_api_response.py
 2 ...
 3 # Assuming you got a `response` from calling an API that might
 4 # have an error key in the `response` if something went wrong
 5
 6 if 'error' in response:
 7     ...  # Parse the error state
 8 else:
 9     ...  # Parse the success state

Здесь есть разница в проверке наличия ключаerror вresponse и получении значения по умолчанию из ключа. Это редкий случай, когда вы на самом деле ищете, если ключ находится в словаре, а не то, каково значение этого ключа.

Общее решение:tryexcept

Как и в случае с любым исключением, вы всегда можете использовать блокtryexcept, чтобы изолировать код, который может привести к возникновению исключения, и предоставить решение для резервного копирования.

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

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5
 6 try:
 7     print(f'{person} is {ages[person]} years old.')
 8 except KeyError:
 9     print(f"{person}'s age is unknown.")

Здесь вы можете увидеть нормальный случай в блокеtry печати имени и возраста человека. Резервный случай находится в блокеexcept, где, еслиKeyError поднимается в нормальном случае, тогда резервный вариант должен напечатать другое сообщение.

Блочное решениеtryexcept также является отличным решением для других мест, которые могут не поддерживать.get() или операторin. Это также лучшее решение, еслиKeyError поднимается из кода другого человека.

Вот пример, снова использующий пакетzipfile. На этот раз блокtryexcept дает нам способ остановить исключениеKeyError от остановки программы:

>>>

>>> from zipfile import ZipFile
>>> zip = ZipFile('the_zip_file.zip')
>>> try:
...     zip.getinfo('something')
... except KeyError:
...     print('Can not find "something"')
...
Can not find "something"

Поскольку классZipFile не предоставляет.get(), как это делает словарь, вам необходимо использовать решениеtryexcept. В этом примере вам не нужно заранее знать, какие значения допустимы для передачи.getinfo().

Заключение

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

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

Если проблема заключается в поиске ключа словаря в вашем собственном коде, вы можете переключиться с доступа к ключу непосредственно в словаре на использование более безопасного метода.get() с возвращаемым значением по умолчанию. Если проблема не в вашем собственном коде, то использование блокаtryexcept — лучший вариант для управления потоком кода.

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

It would help if you posted the text of the message rather than a screen shot. That’s much easier to read and it avoids any moderation delays.

For those reading along, the text is

***Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Pintentions.ViewController ***> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key eIntentionCell.'

There’s also a truncated backtrace that would be super useful to see in full )-:

Looking at that backtrace it seems that frame 5 is your code. The name is mangled but it looks like the

addIntention

method of your

ViewController

class. Somehow this is causing UIKit (frame 4) to attempt to set the

eIntentionCell

property on the

ViewController

instance, and that view controller doesn’t declare a

eIntentionCell

property.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Согласно официальной документации Python 3, ошибка KeyError возникает, когда  ключ набора (словаря) не найден в наборе существующих ключей.

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

rana@Brahma: ~$ python3
Python 3.5.2 (default, Jul 10 2019, 11:58:48) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = dict()
>>> a["key1"] = "value1"
>>> print(a["key2"])
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'key2'
>>> 

Доступ к ключам словаря:

Для доступа к ключам словаря мы используем квадратные скобки [ ].

>>> gender = dict()
>>> gender["m"] = "Male"
>>> gender["f"] = "Female"
>>> gender["m"]
'Male'
>>> 

Однако вышеуказанный способ, то есть использование квадратных скобок, имеет один недостаток. Если ключ не существует, мы получаем KeyError.

>>> gender["k"]
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'k'
>>> 

Удаление несуществующего ключа:

>>> del gender["h"]
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'h'
>>> 

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

— Используйте метод get()

Мы можем получить значение ключа из словаря, используя метод get. Если пара ключ-значение не существует для данного ключа в словаре, то возвращается None, иначе возвращается значение, соответствующее этому ключу. Это рекомендуемый способ.

>>> gender.get("m")
'Male'
>>> gender.get("k")
>>> 
>>> print(gender.get("k") is None)
True
>>>

Вы можете передать второй необязательный параметр в вызове get(), который является значением, возвращаемым, если ключ не существует в словаре. Значением по умолчанию этого второго параметра является None.

— проверить наличие ключа

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

gender = dict()
gender["m"] = "Male"
gender["f"] = "Female"

if "k" in gender:
  print("Key k exists in gender")
else:
  print("Key k doesn't exists in gender")

— Используйте try-exc

Если вы не используете или не хотите использовать метод get для доступа к ключам в словаре, используйте блок try-exc.

gender = dict()
gender["m"] = "Male"
gender["f"] = "Female"

try:
  value = gender["k"]
except KeyError:
  print("Key error. Do something else")
except Exception:
  print("Some other error")

— Получить все ключи и перебрать словарь

Мы можем использовать метод keys(), чтобы получить список всех ключей в словаре, а затем выполнить итерацию по этому списку и получить доступ к значениям в словаре.

gender = dict()
gender["m"] = "Male"
gender["f"] = "Female"

keys = gender.keys()

for key in keys:
  print(gender[key])

— Или вы можете напрямую перебирать словарь для пар ключ и значение, используя метод items().

gender = dict()
gender["m"] = "Male"
gender["f"] = "Female"

for item in gender.items():
  print(item[0], item[1])

Аналогично, для удаления значения ключа из словаря мы можем использовать метод pop() вместо del.

Однако, в отличие от метода get(), метод pop() выбрасывает keyError, если удаляемый ключ не существует и второй параметр не передается.

Таким образом, чтобы избежать ошибки KeyError в случае удаления ключа, мы должны передать значение по умолчанию, которое будет возвращено, если ключ не найден, в качестве второго параметра для pop()

>>> 
>>> gender.pop("m")
'Male'
>>> gender.keys()
dict_keys(['f'])
>>> gender.pop("k")
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'k'
>>> gender.pop("k", None)
>>> 

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python KeyError Exceptions and How to Handle Them

Python’s KeyError exception is a common exception encountered by beginners. Knowing why a KeyError can be raised and some solutions to prevent it from stopping your program are essential steps to improving as a Python programmer.

By the end of this tutorial, you’ll know:

  • What a Python KeyError usually means
  • Where else you might see a KeyError in the standard library
  • How to handle a KeyError when you see it

What a Python KeyError Usually Means

A Python KeyError exception is what is raised when you try to access a key that isn’t in a dictionary (dict).

Python’s official documentation says that the KeyError is raised when a mapping key is accessed and isn’t found in the mapping. A mapping is a data structure that maps one set of values to another. The most common mapping in Python is the dictionary.

The Python KeyError is a type of LookupError exception and denotes that there was an issue retrieving the key you were looking for. When you see a KeyError, the semantic meaning is that the key being looked for could not be found.

In the example below, you can see a dictionary (ages) defined with the ages of three people. When you try to access a key that is not in the dictionary, a KeyError is raised:

>>>

>>> ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
>>> ages['Michael']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Michael'

Here, attempting to access the key 'Michael' in the ages dictionary results in a KeyError being raised. At the bottom of the traceback, you get the relevant information:

  • The fact that a KeyError was raised
  • The key that couldn’t be found, which was 'Michael'

The second-to-last line tells you which line raised the exception. This information is more helpful when you execute Python code from a file.

In the program below, you can see the ages dictionary defined again. This time, you will be prompted to provide the name of the person to retrieve the age for:

 1# ages.py
 2
 3ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4person = input('Get age for: ')
 5print(f'{person} is {ages[person]} years old.')

This code will take the name that you provide at the prompt and attempt to retrieve the age for that person. Whatever you type in at the prompt will be used as the key to the ages dictionary, on line 4.

Repeating the failed example from above, we get another traceback, this time with information about the line in the file that the KeyError is raised from:

$ python ages.py
Get age for: Michael
Traceback (most recent call last):
File "ages.py", line 4, in <module>
  print(f'{person} is {ages[person]} years old.')
KeyError: 'Michael'

The program fails when you give a key that is not in the dictionary. Here, the traceback’s last few lines point to the problem. File "ages.py", line 4, in <module> tells you which line of which file raised the resulting KeyError exception. Then you are shown that line. Finally, the KeyError exception provides the missing key.

So you can see that the KeyError traceback’s final line doesn’t give you enough information on its own, but the lines before it can get you a lot closer to understanding what went wrong.

Where Else You Might See a Python KeyError in the Standard Library

The large majority of the time, a Python KeyError is raised because a key is not found in a dictionary or a dictionary subclass (such as os.environ).

In rare cases, you may also see it raised in other places in Python’s Standard Library, such as in the zipfile module, if an item is not found in a ZIP archive. However, these places keep the same semantic meaning of the Python KeyError, which is not finding the key requested.

In the following example, you can see using the zipfile.ZipFile class to extract information about a ZIP archive using .getinfo():

>>>

>>> from zipfile import ZipFile
>>> zip_file = ZipFile('the_zip_file.zip')
>>> zip_file.getinfo('something')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/python/installation/zipfile.py", line 1304, in getinfo
  'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'something' in the archive"

This doesn’t really look like a dictionary key lookup. Instead, it is a call to zipfile.ZipFile.getinfo() that raises the exception.

The traceback also looks a little different with a little more information given than just the missing key: KeyError: "There is no item named 'something' in the archive".

The final thing to note here is that the line that raised the KeyError isn’t in your code. It is in the zipfile code, but previous lines of the traceback indicate which lines in your code caused the problem.

When You Need to Raise a Python KeyError in Your Own Code

There may be times when it makes sense for you to raise a Python KeyError exception in your own code. This can be done by using the raise keyword and calling the KeyError exception:

Usually, the message would be the missing key. However, as in the case of the zipfile package, you could opt to give a bit more information to help the next developer better understand what went wrong.

If you decide to raise a Python KeyError in your own code, just make sure that your use case matches the semantic meaning behind the exception. It should denote that the key being looked for could not be found.

How to Handle a Python KeyError When You See It

When you encounter a KeyError, there are a few standard ways to handle it. Depending on your use case, some of these solutions might be better than others. The ultimate goal is to stop unexpected KeyError exceptions from being raised.

The Usual Solution: .get()

If the KeyError is raised from a failed dictionary key lookup in your own code, you can use .get() to return either the value found at the specified key or a default value.

Much like the age retrieval example from before, the following example shows a better way to get the age from the dictionary using the key provided at the prompt:

 1# ages.py
 2
 3ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4person = input('Get age for: ')
 5age = ages.get(person)
 6
 7if age:
 8    print(f'{person} is {age} years old.')
 9else:
10    print(f"{person}'s age is unknown.")

Here, line 5 shows how you can get the age value from ages using .get(). This will result in the age variable having the age value found in the dictionary for the key provided or a default value, None in this case.

This time, you will not get a KeyError exception raised because of the use of the safer .get() method to get the age rather than attempting to access the key directly:

$ python ages.py
Get age for: Michael
Michael's age is unknown.

In the example execution above, the KeyError is no longer raised when a bad key is provided. The key 'Michael' is not found in the dictionary, but by using .get(), we get a None returned rather than a raised KeyError.

The age variable will either have the person’s age found in the dictionary or the default value (None by default). You can also specify a different default value in the .get() call by passing a second argument.

This is line 5 from the example above with a different default age specified using .get():

age = ages.get(person, 0)

Here, instead of 'Michael' returning None, it would return 0 because the key isn’t found, and the default value to return is now 0.

The Rare Solution: Checking for Keys

There are times when you need to determine the existence of a key in a dictionary. In these cases, using .get() might not give you the correct information. Getting a None returned from a call to .get() could mean that the key wasn’t found or that the value found at the key in the dictionary is actually None.

With a dictionary or dictionary-like object, you can use the in operator to determine whether a key is in the mapping. This operator will return a Boolean (True or False) value indicating whether the key is found in the dictionary.

In this example, you are getting a response dictionary from calling an API. This response might have an error key value defined in the response, which would indicate that the response is in an error state:

 1# parse_api_response.py
 2...
 3# Assuming you got a `response` from calling an API that might
 4# have an error key in the `response` if something went wrong
 5
 6if 'error' in response:
 7    ...  # Parse the error state
 8else:
 9    ...  # Parse the success state

Here, there is a difference in checking to see if the error key exists in the response and getting a default value from the key. This is a rare case where what you are actually looking for is if the key is in the dictionary and not what the value at that key is.

The General Solution: try except

As with any exception, you can always use the try except block to isolate the potential exception-raising code and provide a backup solution.

You can use the try except block in a similar example as before, but this time providing a default message to be printed should a KeyError be raised in the normal case:

 1# ages.py
 2
 3ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4person = input('Get age for: ')
 5
 6try:
 7    print(f'{person} is {ages[person]} years old.')
 8except KeyError:
 9    print(f"{person}'s age is unknown.")

Here, you can see the normal case in the try block of printing the person’s name and age. The backup case is in the except block, where if a KeyError is raised in the normal case, then the backup case is to print a different message.

The try except block solution is also a great solution for other places that might not support .get() or the in operator. It is also the best solution if the KeyError is being raised from another person’s code.

Here is an example using the zipfile package again. This time, the try except block gives us a way to stop the KeyError exception from stopping the program:

>>>

>>> from zipfile import ZipFile
>>> zip = ZipFile('the_zip_file.zip')
>>> try:
...     zip.getinfo('something')
... except KeyError:
...     print('Can not find "something"')
...
Can not find "something"

Since the ZipFile class does not provide .get(), like the dictionary does, you need to use the try except solution. In this example, you don’t have to know ahead of time what values are valid to pass to .getinfo().

Conclusion

You now know some common places where Python’s KeyError exception could be raised and some great solutions you could use to prevent them from stopping your program.

Now, the next time you see a KeyError raised, you will know that it is probably just a bad dictionary key lookup. You will also be able to find all the information you need to determine where the error is coming from by looking at the last few lines of the traceback.

If the problem is a dictionary key lookup in your own code, then you can switch from accessing the key directly on the dictionary to using the safer .get() method with a default return value. If the problem isn’t coming from your own code, then using the try except block is your best bet for controlling your code’s flow.

Exceptions don’t have to be scary. Once you know how to understand the information provided to you in their tracebacks and the root cause of the exception, then you can use these solutions to make your programs flow more predictably.

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python KeyError Exceptions and How to Handle Them

Понравилась статья? Поделить с друзьями:
  • Clash of clans как изменить вид деревни
  • Clarke error grid
  • Clang fatal error iostream file not found
  • Clang error unsupported option fopenmp
  • Clang error no such file or directory