Номера телефонов возвращение python

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

Напишите программу, проверяющую корректность введенного номера сотового телефона в РФ по следующим критериям:
Номер может начинаться как с +7, так и с 8
Допускается любое количество любых пробельных символов в любом месте, например, +7 905 3434 341.
Допускается наличие в любом месте одной пары скобок (обязательно пары), например: 8 (905) 3434 341.
Допускается наличие любого количества знаков -, только не подряд (—), не в начале и не в конце. Например,
+7 905-34-34-341.

Если введенный номер корректен, он преобразуется к формату +79053434341. То есть 8 заменяется на +7, а все другие символы-НЕцифры убираются. В итоговой записи остается 11 цифр.
Если же номер не удовлетворяет перечисленным условиям, выводится слово error.

Пример 1
Ввод Вывод
+7(902)123-4567
+79021234567
Пример 2
Ввод Вывод
8(902)1-2-3-45-67
+79021234567
Пример 3
Ввод Вывод
504))635(22))9 9
error
Пример 4
Ввод Вывод
8—9019876543-22-3—4
error

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

Система проверки сайта не принимает решение, пожалуйста подскажите где ошибка.

Собственно задача:

1002.Телефонные номера

Ограничение времени: 2.0 секунды
Ограничение памяти: 64 МБ

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

1 ij    2 abc   3 def
4 gh    5 kl    6 mn
7 prs   8 tuv   9 wxy
        0 oqz

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

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

Исходные данные

Ввод состоит из набора тестов. Первая строка каждого теста содержит номер телефона,
к которому нужно подобрать мнемонику. Номер состоит не более чем из 100 цифр.
Вторая строка содержит общее количество слов в словаре (максимум 50 000).
Каждая из оставшихся строк содержит одно слово,
состоящее не более чем из 50 строчных латинских букв.
Общий размер ввода не превосходит 300 килобайт.
Последняя строка ввода содержит число −1.

Результат

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


Ввод и вывод данные авторами для примера:

7325189087
5
it
your
reality
real
our
4294967296
5
it
your
reality
real
our
-1
# Ожидаемый результат  
reality our
No solution.

Мои вводные для теста:

2272583262772
11
ba
ra
ku
k
ss
u
ma
da
m
a
ssa
-1

По логике ответ должен быть

ba ra ku da ma ssa

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

['ba', 'ra', 'ku', 'da', 'm', 'a', 'ss', 'a']
['a', 'a', 'ra', 'ku', 'da', 'm', 'a', 'ss', 'a']

И соответственно оптимальным код считает:

ba ra ku da m a ss a

Ну и соответственно валидатор не принимает это решение.
Подскажите пожалуйста где косяк

Мое решение:

keyboard = {'1': 'ij', '2': 'abc', '3': 'def',
            '4': 'gh', '5': 'kl', '6': 'mn',
            '7': 'prs', '8': 'tuv', '9': 'wxy',
            '0': 'oqz'}

while True:
    phone_num = input()
    solutions = []
    if phone_num == '-1':
        break
    phone_len = len(phone_num)
    words = [input() for _ in range(int(input()))]
    collector = []
    for word in words:
        if len(word) > phone_len:
            continue

        solution = []
        for i in range(len(word)):
            if word[i] not in keyboard[phone_num[i]]:
                break

        else:
            solution.append(word)
            test_solution = []

            while test_solution != solution:
                test_solution = solution.copy()
                raw_solution = ''.join(solution)
                len_solution = len(raw_solution)
                new_words = [item for item in words if len(item) <= phone_len - len_solution]
                if new_words:
                    for item in new_words:
                        raw_solution = ''.join(solution)
                        len_solution = len(raw_solution)
                        test_string = raw_solution + item
                        len_test_string = len(test_string)
                        if len_test_string > phone_len:
                            continue
                        for s in range(len_solution, len_test_string):
                            if test_string[s] not in keyboard[phone_num[s]]:
                                break
                        else:
                            solution.append(item)

            solutions.append(solution)

    if solutions:
        solutions.sort(key=lambda g: len(g))
        print(*solutions[0])
    else:
        print('No solution.')

Вступление

Проверка телефонных номеров может быть очень сложной задачей. Формат
номера телефона может отличаться от страны к стране. Черт возьми, это
может также отличаться в пределах одной страны! Некоторые страны
используют один и тот же код страны, в то время как некоторые другие
страны используют более одного кода страны. Согласно примеру из
репозитория Google
libphonenumber
GitHub, США, Канада и Карибские острова имеют один и тот же код страны (
+1 ). С другой стороны, на телефонные номера из Косово можно звонить
по сербскому, словенскому и марокканскому кодам стран.

Это лишь некоторые из проблем, связанных с идентификацией или проверкой
телефонных номеров. На первый взгляд, можно хотя бы проверить код страны
телефонного номера с помощью
RegEx . Однако это
означает, что вам нужно будет написать собственное правило RegEx для
каждой страны мира, просто чтобы проверить код страны. Кроме того, у
некоторых операторов мобильной связи есть свои правила (например, для
определенных цифр можно использовать только определенный диапазон
номеров). Вы можете видеть, что ситуация может быстро выйти из-под
контроля и сделать для нас практически невозможным проверку ввода номера
телефона самостоятельно.

К счастью, есть библиотека Python, которая может помочь нам легко и
эффективно пройти процесс проверки. Библиотека Python Phonenumbers
является производным от библиотеки Google libphonenumber , которая
также доступна для других языков программирования, таких как C ++, Java
и JavaScript.

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

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

 import phonenumbers 
 from phonenumbers import carrier, timezone, geocoder 
 
 my_number = phonenumbers.parse("+447986123456", "GB") 
 
 print(phonenumbers.is_valid_number(my_number)) 
 print(carrier.name_for_number(my_number, "en")) 
 print(timezone.time_zones_for_number(my_number)) 
 print(geocoder.description_for_number(my_number, 'en')) 

И вот результат:

 True 
 EE 
 ('Europe/Guernsey', 'Europe/Isle_of_Man', 'Europe/Jersey', 'Europe/London') 
 United Kingdom 

Начнем с настройки нашей среды и установки библиотеки.

Установка телефонных номеров

Сначала давайте создадим и активируем нашу виртуальную среду:

 $ mkdir phonenumbers && cd phonenumbers 
 $ python3 -m venv venv 
 $ . venv/bin/active # venvScriptsactivate.bat on Windows 

Затем устанавливаем библиотеку Python Phonenumbers:

 $ pip3 install Phonenumbers 

В этом руководстве будет использоваться библиотека Phonenumbers версии
8.12.19 .

Теперь мы готовы начать знакомство с библиотекой Phonenumbers.

Разбор номера телефонов номера телефонов Python

Независимо от того, получаете ли вы ввод пользователя из веб-формы или
из других источников, например извлекаете из некоторого текста
(подробнее об этом позже в этом руководстве), входящий номер телефона,
скорее всего, будет строкой. В качестве первого шага, мы должны
разобрать его , используя phonenumbers , и превратить его в
PhoneNumber , например , так , что мы можем использовать его для
проверки и других функций.

Мы можем разобрать номер телефона с помощью метода parse()

 import phonenumbers 
 
 my_string_number = "+40721234567" 
 my_number = phonenumbers.parse(my_string_number) 

Метод phonenumbers.parse() принимает строку номера телефона в качестве
обязательного аргумента. Вы также можете передать информацию о стране в
формате ISO Alpha-2 в качестве необязательного аргумента. Рассмотрим,
например, следующий код:

 my_number = phonenumbers.parse(my_string_number, "RO") 

«RO» означает Румынию в формате ISO Alpha-2. Вы можете проверить другие
коды стран Alpha-2 и цифровые коды на этом
веб-сайте . В этом руководстве для простоты я
буду опускать код страны ISO Alpha-2 для большинства случаев и включать
его только тогда, когда это строго необходимо.

В phonenumbers.parse() уже есть некоторые встроенные базовые правила
проверки, такие как длина числовой строки, проверка нуля в начале или
знак + Обратите внимание, что этот метод вызовет исключение, если
какое-либо из необходимых правил не выполнено. Поэтому не забудьте
использовать его в блоке try / catch в своем приложении .

Теперь, когда мы правильно проанализировали номер телефона, приступим к
проверке.

Подтверждение телефонных номеров с помощью телефонных номеров Python

Phonenumbers имеет два метода проверки действительности телефонного
номера. Основное отличие этих методов — скорость и точность.

Чтобы уточнить, начнем с is_possible_number() :

 import phonenumbers 
 
 my_string_number = "+40021234567" 
 my_number = phonenumbers.parse(my_string_number) 
 print(phonenumbers.is_possible_number(my_number)) 

И результат будет:

 True 

Теперь давайте воспользуемся тем же числом, но на этот раз с методом
is_valid_number()

 import phonenumbers 
 
 my_string_number = "+40021234567" 
 my_number = phonenumbers.parse(my_string_number) 
 print(phonenumbers.is_valid_number(my_number)) 

Несмотря на то, что ввод был таким же, результат был бы другим:

 False 

Причина в том, что метод is_possible_number() быстро угадывает
действительность телефонного номера, проверяя длину проанализированного
номера, в то время как метод is_valid_number() выполняет полную
проверку, проверяя длину, префикс телефонного номера и регион.

При переборе большого списка телефонных номеров использование
phonenumbers.is_possible_number() обеспечит более быстрые результаты
по сравнению с phonenumbers.is_valid_number() . Но, как мы видим
здесь, эти результаты не всегда могут быть точными. Это может быть
полезно для быстрого удаления телефонных номеров, не соответствующих
длине. Так что используйте это на свой страх и риск.

Извлечение и форматирование телефонных номеров с помощью телефонных номеров Python

Пользовательский ввод — не единственный способ получить или собрать
телефонные номера. Например, у вас может быть паук / краулер, который
будет читать определенные страницы с веб-сайта или документа и извлекать
номера телефонов из текстовых блоков. Это звучит как сложная проблема,
но, к счастью, библиотека Phonenumbers предоставляет нам только
необходимые функции с помощью PhoneNumberMatcher(text, region) .

PhoneNumberMatcher принимает текстовый блок и область в качестве
аргумента, а затем выполняет PhoneNumberMatch чтобы вернуть
соответствующие результаты в виде объектов PhoneNumberMatch.

Давайте использовать PhoneNumberMatcher со случайным текстом:

 import phonenumbers 
 
 text_block = "Our services will cost about 2,200 USD and we will deliver the product by the 10.10.2021. For more information, you can call us at +44 7986 123456 or send an e-mail to [email protected] " 
 
 for match in phonenumbers.PhoneNumberMatcher(text_block, "GB"): 
 print(match) 

Это напечатает совпадающие телефонные номера вместе с их индексом в
строке:

 PhoneNumberMatch [131,146) +44 7986 123456 

Возможно, вы заметили, что наш номер отформатирован в стандартизованном
международном формате и разделен пробелами. Это может быть не всегда так
в реальных сценариях. Вы можете получить свой номер в других форматах,
например, разделенный тире или отформатированный в национальном (вместо
международного) формате.

Давайте PhoneNumberMatcher() с другими форматами телефонных номеров:

 import phonenumbers 
 
 text_block = "Our services will cost about 2,200 USD and we will deliver the product by the 10.10.2021. For more information you can call us at +44-7986-123456 or 020 8366 1177 send an e-mail to [email protected] " 
 
 for match in phonenumbers.PhoneNumberMatcher(text_block, "GB"): 
 print(match) 

Это выведет:

 PhoneNumberMatch [130,145) +44-7986-123456 
 PhoneNumberMatch [149,162) 020 8366 1177 

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

Помимо извлечения данных из текста, мы также можем захотеть получить
цифры по одной от пользователя. Представьте, что пользовательский
интерфейс вашего приложения работает аналогично современным мобильным
телефонам и форматирует номера телефонов по мере ввода. Например, на
своей веб-странице вы можете передавать данные в свой API с каждым
onkeyup и использовать AsYouTypeFormatter() для форматируйте
телефонный номер с каждой входящей цифрой.

Поскольку часть пользовательского интерфейса выходит за рамки этой
статьи, мы будем использовать базовый пример для AsYouTypeFormatter .
Чтобы смоделировать форматирование на лету, давайте перейдем к
интерпретатору Python:

 >>> import phonenumbers 
 >>> formatter = phonenumbers.AsYouTypeFormatter("TR") 
 >>> formatter.input_digit("3") 
 '3' 
 >>> formatter.input_digit("9") 
 '39' 
 >>> formatter.input_digit("2") 
 '392' 
 >>> formatter.input_digit("2") 
 '392 2' 
 >>> formatter.input_digit("2") 
 '392 22' 
 >>> formatter.input_digit("1") 
 '392 221' 
 >>> formatter.input_digit("2") 
 '392 221 2' 
 >>> formatter.input_digit("3") 
 '392 221 23' 
 >>> formatter.input_digit("4") 
 '392 221 23 4' 
 >>> formatter.input_digit("5") 
 '392 221 23 45' 

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

Библиотека Phonenumbers также предоставила нам format_number() . Этот
метод позволяет нам преобразовать телефонные номера в три хорошо
известных стандартизованных формата. Национальный, Международный и E164.
Национальные и международные форматы говорят сами за себя, в то время
как формат E164 — это международный формат телефонных номеров, который
гарантирует, что номера телефонов ограничены 15 цифрами и имеют формат
{+} {код страны} {номер с кодом города} . Для получения дополнительной
информации о E164 вы можете проверить эту страницу в
Википедии .

Начнем с национального форматирования:

 import phonenumbers 
 
 my_number = phonenumbers.parse("+40721234567") 
 national_f = phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.NATIONAL) 
 print(national_f) 

Это вернет строку номера телефона с красивым интервалом в национальном
формате:

 0721 234 567 

Теперь попробуем отформатировать национальный номер как международный:

 import phonenumbers 
 
 my_number = phonenumbers.parse("0721234567", "RO") # "RO" is ISO Alpha-2 code for Romania 
 international_f = phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.INTERNATIONAL) 
 print(international_f) 

Приведенный выше код вернет строку с номером телефона с аккуратным
интервалом:

 +40 721 234 567 

Обратите внимание, что мы передали "RO" в качестве второго параметра в
метод parse() . Поскольку введенный номер является национальным
номером, он не имеет префикса кода страны, который указывал бы на
страну. В этих случаях нам нужно указать страну с ее кодом ISO Alpha-2,
чтобы получить точный результат. Исключение числового кода страны и кода
страны ISO Alpha-2 вызовет исключение
NumberParseException: (0) Missing or invalid default region. .

Теперь попробуем E164 форматирования E164. В качестве входных данных
мы передадим национальную строку:

 import phonenumbers 
 
 my_number = phonenumbers.parse("0721234567", "RO") 
 e164_f=phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.E164) 
 print(e164_f) 

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

 +40721234567 

Это очень полезно, если вы хотите передать число в фоновый API.
API-интерфейсы нередко ожидают, что телефонные номера будут строками без
пробелов.

Получить дополнительную информацию о номере телефона

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

Для начала воспользуемся методом description_for_number() из класса
geocoder Этот метод принимает в качестве параметров проанализированный
номер телефона и короткое название языка.

Давайте попробуем это с нашим предыдущим фальшивым номером:

 import phonenumbers 
 from phonenumbers import geocoder 
 
 my_number = phonenumbers.parse("+447986123456") 
 print(geocoder.description_for_number(my_number, "en")) 

Это распечатает страну происхождения телефонного номера:

 United Kingdom 

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

 import phonenumbers 
 from phonenumbers import geocoder 
 
 my_number = phonenumbers.parse("+447986123456") 
 print(geocoder.description_for_number(my_number, "ru")) 

А вот результат, в котором по-русски написано Великобритания:

 Соединенное Королевство 

Вы можете попробовать его с другими языками по вашему выбору, такими как
«de», «fr», «zh» и т. Д.

Как упоминалось ранее, вы можете сгруппировать свои телефонные номера по
их операторам связи, поскольку в большинстве случаев это повлияет на
стоимость. Чтобы уточнить, библиотека Phonenumbers, вероятно,
предоставит большинство имен операторов точно, но не на 100%.

Сегодня в большинстве стран можно получить свой номер у одного оператора
связи, а затем перенести тот же номер на другого оператора, оставив при
этом номер телефона неизменным. Поскольку Phonenumbers — это просто
автономная библиотека Python, эти изменения невозможно обнаружить.
Поэтому лучше рассматривать названия операторов как справку, а не как
факт.

Мы будем использовать метод name_for_number() из класса carrier

 import phonenumbers 
 from phonenumbers import carrier 
 
 my_number = phonenumbers.parse("+40721234567") 
 print(carrier.name_for_number(my_number, "en")) 

Если возможно, отобразится исходный оператор телефонного номера:

 Vodafone 

Примечание . Как указано в исходных документах Python Phonenumbers,
информация о операторах связи доступна для мобильных номеров в некоторых
странах, а не во всех.

Еще одна важная информация о номере телефона — это часовой пояс. Метод
time_zones_for_number() вернет список часовых поясов, которым
принадлежит номер. Мы импортируем его из phonenumbers.timezone :

 import phonenumbers 
 from phonenumbers import timezone 
 
 my_number = phonenumbers.parse("+447986123456") 
 print(timezone.time_zones_for_number(my_number)) 

Это напечатает следующие часовые пояса:

 ('Europe/Guernsey', 'Europe/Isle_of_Man', 'Europe/Jersey', 'Europe/London') 

На этом мы завершаем наше руководство по телефонным номерам Python.

Заключение

Мы узнали, как анализировать телефонные номера с помощью parse() ,
извлекать числа из текстовых блоков с помощью PhoneNumberMatcher() ,
получать номера телефонов по цифрам и форматировать их с помощью
AsYouTypeFormatter() , использовать различные методы проверки с
is_possible_number() и is_possible_number() , форматируйте числа с
помощью NATIONAL , INTERNATIONAL и E164 и извлекайте
дополнительную информацию из номеров телефонов с помощью классов
geocoder , carrier и timezone

Не забудьте проверить исходный репозиторий библиотеки Phonenumbers на
GitHub . Также,
если у вас есть какие-либо вопросы, не стесняйтесь комментировать ниже.

I have some style notes about your script since the others covered the workings so well. The Python style guide PEP0008 is an invaluable resource for this.

I’ll start with comments. You should make comments, clear, to the point and well readable. You have issues with your opening block:

#My approach is to convert the whole keypad into graph with nodes representing number and edges represent there is a path
#exists between two nodes. This graph is an undirected graph which means it is bidirectional
#Now I am going to define a dictionary with key repserenting the node(Number on Keypad) and values representing direct connection to node.
#What you see below is the movement of knight represented by key value pair
#It is extremely important to avoid loop in the graph otherwise it will go into infinte recursion.

Comments should have a space at the start, after the #. Lines should also try to be under 79 characters. You might think this adds lines, but really it encourages you to be more brief. As for what you’re actually saying, it’s more of a preamble than any explanation of the code or the problem. You begin saying «My approach», but you haven’t said what you’re approaching. If this is for the employers you send it in an email or explain it in conversation. Comments are for making the code’s function clear, not describing your ideas about the way it’s done. I’d rewrite this to be a brief explanation of the problem. Don’t explain your approach, it’s better to let the code do that with comments along the way to clarify more confusing parts.

Inline comments should be rare. They should only occur as brief comments that best fit on the same line instead of their own line. This isn’t a great example:

knight = {'1': ['6', '8'],  #movement of knight

It seems like it’s supposed to be relevant to that particular row rather than the whole knight value. Put it on the line above.

# Movement of knight
knight = {'1': ['6', '8'],  

Now, your second inline comment is worse because it’s too long. Your big long comment wouldn’t fit the requirement even on a line of it’s own. Split it onto two lines, and take it out of the dictionary.

# Movement of knight
# This is how the graph will look for Knight with key representing
# the starting point and where they can go from there.
knight = {'1': ['6', '8'],  

…it’s also unclear. with key representing the starting point and where they can go from there? You should write comments that can explain your code to someone who doesn’t even know the brief, which this doesn’t really do. I’d prefer it as:

# Movement of knight
# Keys represent starting points and values contain possible moves.
knight = {'1': ['6', '8'],  

Shorter, clearer and clearly delineates what the values mean.

Still on comments, I don’t need to know about redundancies you’ve left out unless they’re confusing me:

#removed the path which will go into special characters since phone number cannot contain that
'5': ['1', '3', '7', '9'],  #path leading to #, * are ignored

You’re mostly saying the same thing twice, but also the bishop wouldn’t move from 5 to * or # anyway, it’d only move there from 8. I’d just remove both these comments though.

Now, for your docstring you seem to have taken on the javadocs style, which is not the Python way, not to mention you actually misused it anyway by mislabelling parameters, and leaving out information about them to put in a comment instead. Docstrings have their own PEP, but here’s one suggestion:

'''Calculate a list of the valid phone numbers for Knight's movement.

Knight contains the knight's movement and start is it's starting key.
Path is used to build up the phone number, it shouldn't be supplied.'''

This is clearer, gives an indication of how to use the function and actually explains the context more.

About the name, knightFindPhoneNumbers is both verbose and the wrong naming convention for Python. Python uses snake_case, like knight_find_phone_numbers. The verbosity is a sign that the function is too specific, as pointed out you could make one function do both. find_phone_numbers is pretty good then, I prefer calculate_phone_numbers personally, as you’re determining values, not just finding them.

Again, back to comments:

if len(path) == 7:  #if the total number of length of path is 7 return the path. It means we found a valid phone number
    return [path] #we found one valid phone number

The second one here is totally redundant as you just said it one line before, but that first line contains a lot of redundancy. len(path) == 7 says if the total number of length of path is 7 much more concisely than you, so you can leave it out. It is a good idea to have a much shorter inline comment here though:

if len(path) == 7:
    return [path]  # Valid phone number

It is good to use an inline here, just to highlight abstractly what this means in a couple brief words.

This is confusing and sorely lacking a comment:

if not knight.has_key(start):
    return []

Is this an error? Something that shouldn’t be happening? It seems like it is, and if so then you should really mark it as an error with raise ValueError("Not a valid starting point."). Returning an empty list is confusing, especially in a recursive function where that might mean an incomplete number is raised. If returning the empty list is specific intentional behaviour, explain it with a comment. But if this is your error handling, you should actually raise an error.

I’m confused why you’re testing if node on knight[start]. You realise that any non empty string will evaluate as True? Meaning this should always be True and I can’t see why it would be False or what it would mean. It’s either unnecessary code or it’s actually a test I’ve misunderstood.

chessPlayer isn’t a clear name either. It makes it sound like it’s a game, when really you just want to get chess_piece. Also to check user input, it’s good to use .lower() as well as strip so that you can make sure all the characters are lowercase, in case the user entered Knight or even KNIGHT.

I have some style notes about your script since the others covered the workings so well. The Python style guide PEP0008 is an invaluable resource for this.

I’ll start with comments. You should make comments, clear, to the point and well readable. You have issues with your opening block:

#My approach is to convert the whole keypad into graph with nodes representing number and edges represent there is a path
#exists between two nodes. This graph is an undirected graph which means it is bidirectional
#Now I am going to define a dictionary with key repserenting the node(Number on Keypad) and values representing direct connection to node.
#What you see below is the movement of knight represented by key value pair
#It is extremely important to avoid loop in the graph otherwise it will go into infinte recursion.

Comments should have a space at the start, after the #. Lines should also try to be under 79 characters. You might think this adds lines, but really it encourages you to be more brief. As for what you’re actually saying, it’s more of a preamble than any explanation of the code or the problem. You begin saying «My approach», but you haven’t said what you’re approaching. If this is for the employers you send it in an email or explain it in conversation. Comments are for making the code’s function clear, not describing your ideas about the way it’s done. I’d rewrite this to be a brief explanation of the problem. Don’t explain your approach, it’s better to let the code do that with comments along the way to clarify more confusing parts.

Inline comments should be rare. They should only occur as brief comments that best fit on the same line instead of their own line. This isn’t a great example:

knight = {'1': ['6', '8'],  #movement of knight

It seems like it’s supposed to be relevant to that particular row rather than the whole knight value. Put it on the line above.

# Movement of knight
knight = {'1': ['6', '8'],  

Now, your second inline comment is worse because it’s too long. Your big long comment wouldn’t fit the requirement even on a line of it’s own. Split it onto two lines, and take it out of the dictionary.

# Movement of knight
# This is how the graph will look for Knight with key representing
# the starting point and where they can go from there.
knight = {'1': ['6', '8'],  

…it’s also unclear. with key representing the starting point and where they can go from there? You should write comments that can explain your code to someone who doesn’t even know the brief, which this doesn’t really do. I’d prefer it as:

# Movement of knight
# Keys represent starting points and values contain possible moves.
knight = {'1': ['6', '8'],  

Shorter, clearer and clearly delineates what the values mean.

Still on comments, I don’t need to know about redundancies you’ve left out unless they’re confusing me:

#removed the path which will go into special characters since phone number cannot contain that
'5': ['1', '3', '7', '9'],  #path leading to #, * are ignored

You’re mostly saying the same thing twice, but also the bishop wouldn’t move from 5 to * or # anyway, it’d only move there from 8. I’d just remove both these comments though.

Now, for your docstring you seem to have taken on the javadocs style, which is not the Python way, not to mention you actually misused it anyway by mislabelling parameters, and leaving out information about them to put in a comment instead. Docstrings have their own PEP, but here’s one suggestion:

'''Calculate a list of the valid phone numbers for Knight's movement.

Knight contains the knight's movement and start is it's starting key.
Path is used to build up the phone number, it shouldn't be supplied.'''

This is clearer, gives an indication of how to use the function and actually explains the context more.

About the name, knightFindPhoneNumbers is both verbose and the wrong naming convention for Python. Python uses snake_case, like knight_find_phone_numbers. The verbosity is a sign that the function is too specific, as pointed out you could make one function do both. find_phone_numbers is pretty good then, I prefer calculate_phone_numbers personally, as you’re determining values, not just finding them.

Again, back to comments:

if len(path) == 7:  #if the total number of length of path is 7 return the path. It means we found a valid phone number
    return [path] #we found one valid phone number

The second one here is totally redundant as you just said it one line before, but that first line contains a lot of redundancy. len(path) == 7 says if the total number of length of path is 7 much more concisely than you, so you can leave it out. It is a good idea to have a much shorter inline comment here though:

if len(path) == 7:
    return [path]  # Valid phone number

It is good to use an inline here, just to highlight abstractly what this means in a couple brief words.

This is confusing and sorely lacking a comment:

if not knight.has_key(start):
    return []

Is this an error? Something that shouldn’t be happening? It seems like it is, and if so then you should really mark it as an error with raise ValueError("Not a valid starting point."). Returning an empty list is confusing, especially in a recursive function where that might mean an incomplete number is raised. If returning the empty list is specific intentional behaviour, explain it with a comment. But if this is your error handling, you should actually raise an error.

I’m confused why you’re testing if node on knight[start]. You realise that any non empty string will evaluate as True? Meaning this should always be True and I can’t see why it would be False or what it would mean. It’s either unnecessary code or it’s actually a test I’ve misunderstood.

chessPlayer isn’t a clear name either. It makes it sound like it’s a game, when really you just want to get chess_piece. Also to check user input, it’s good to use .lower() as well as strip so that you can make sure all the characters are lowercase, in case the user entered Knight or even KNIGHT.

Introduction

Validating phone numbers can be a very challenging task. The format of a phone number can vary from one country to another. Heck, it can also vary within the same country! Some countries share the same country code, while some other countries use more than one country code. According to an example from the Google’s libphonenumber GitHub repository, USA, Canada, and Caribbean islands, all share the same country code (+1). On the other hand, it is possible to call the phone numbers from Kosovo by Serbian, Slovenian and Moroccan country codes.

These are only a few of the challenges in identifying or validating phone numbers. At first glance, one can at least validate the country code of a phone number with a RegEx. However, this means that you would have to write a custom RegEx rule for every country in the world, just to validate a country code. On top of that, some mobile phone carriers have their own rules (for example, certain digits can only use a certain range of numbers). You can see that things can quickly get out of hand and make it almost impossible for us to validate phone number inputs by ourselves.

Luckily, there is a Python library that can help us to get through the validation process easily and efficiently. The Python Phonenumbers library is derived from Google’s libphonenumber library, which is also available for other programming languages like C++, Java, and JavaScript.

In this tutorial, we’ll learn how to parse, validate and extract phone numbers, as well as how to extract additional information from the phone number(s) like the carrier, timezone, or geocoder details.

Using the library is very straight-forward and it’s typically used like this:

import phonenumbers
from phonenumbers import carrier, timezone, geocoder

my_number = phonenumbers.parse("+447986123456", "GB")

print(phonenumbers.is_valid_number(my_number))
print(carrier.name_for_number(my_number, "en"))
print(timezone.time_zones_for_number(my_number))
print(geocoder.description_for_number(my_number, 'en'))

And here’s the output:

True
EE
('Europe/Guernsey', 'Europe/Isle_of_Man', 'Europe/Jersey', 'Europe/London')
United Kingdom

Let’s get started by setting up our environment and installing the library.

Installing phonenumbers

First, let’s create and activate our virtual environment:

$ mkdir phonenumbers && cd phonenumbers
$ python3 -m venv venv
$ . venv/bin/active # venvScriptsactivate.bat on Windows

Then we install the Python Phonenumbers library:

$ pip3 install Phonenumbers

This tutorial will use Phonenumbers library version of 8.12.19.

Now we are ready to start discovering the Phonenumbers library.

Parse Phone Numbers with Python phonenumbers

Whether you get user input from a web form or other sources, like extracting from some text (more on that later in this tutorial), the input phone number will most likely be a string. As a first step, we’ll need to parse it using phonenumbers, and turn it into a PhoneNumber instance so that we can use it for validation and other functionalities.

We can parse the phone number using the parse() method:

import phonenumbers

my_string_number = "+40721234567"
my_number = phonenumbers.parse(my_string_number)

The phonenumbers.parse() method takes a phone number string as a required argument. You can also pass the country information in ISO Alpha-2 format as an optional argument. Take, for example, the following code into consideration:

my_number = phonenumbers.parse(my_string_number, "RO")

«RO» stands for Romania in ISO Alpha-2 format. You can check other Alpha-2 and numeric country codes from this website. In this tutorial, for simplicity, I will omit the ISO Alpha-2 country code for most cases and include it only when it’s strictly necessary.

The phonenumbers.parse() method already has some built-in basic validation rules like the length of a number string, or checking a leading zero, or for a + sign. Note that this method will throw an exception when any of the needed rules are not fulfilled. So remember to use it in a try/catch block in your application.

Now that we got our phone number parsed correctly, let’s proceed to validation.

Validate Phone Numbers with Python Phonenumbers

Phonenumbers has two methods to check the validity of a phone number. The main difference between these methods is the speed and accuracy.

To elaborate, let’s start with is_possible_number():

import phonenumbers

my_string_number = "+40021234567"
my_number = phonenumbers.parse(my_string_number)
print(phonenumbers.is_possible_number(my_number))

And the output would be:

True

Now let’s use the same number, but with the is_valid_number() method this time:

import phonenumbers

my_string_number = "+40021234567"
my_number = phonenumbers.parse(my_string_number)
print(phonenumbers.is_valid_number(my_number))

Even though the input was the same, the result would be different:

False

The reason is that the is_possible_number() method makes a quick guess on the phone number’s validity by checking the length of the parsed number, while the is_valid_number() method runs a full validation by checking the length, phone number prefix, and region.

When iterating over a large list of phone numbers, using phonenumbers.is_possible_number() would provide faster results comparing to the phonenumbers.is_valid_number(). But as we see here, these results may not always be accurate. It can be useful to quickly eliminate phone numbers that do not comply with the length. So use it at your own risk.

Extract and Format Phone Numbers with Python Phonenumbers

User input is not the only way to get or collect phone numbers. For instance, you may have a spider/crawler that would read certain pages from a website or a document and would extract the phone numbers from the text blocks. It sounds like a challenging problem but luckily, the Phonenumbers library provides us just the functionality we need, with the PhoneNumberMatcher(text, region) method.

PhoneNumberMatcher takes a text block and a region as an argument then iterates over to return the matching results as PhoneNumberMatch objects.

Let’s use PhoneNumberMatcher with a random text:

import phonenumbers

text_block = "Our services will cost about 2,200 USD and we will deliver the product by the 10.10.2021. For more information, you can call us at +44 7986 123456 or send an e-mail to [email protected]"

for match in phonenumbers.PhoneNumberMatcher(text_block, "GB"):
    print(match)

This will print the matching phone numbers along with their index in the string:

PhoneNumberMatch [131,146) +44 7986 123456

You may have noticed that our number is formatted in the standardized international format and divided by the spaces. This may not always be the case in real-life scenarios. You may receive your number in other formats, like divided by dashes or formatted to the national (instead of the international) format.

Let’s put the PhoneNumberMatcher() method to the test with other phone number formats:

import phonenumbers

text_block = "Our services will cost about 2,200 USD and we will deliver the product by the 10.10.2021. For more information you can call us at +44-7986-123456 or 020 8366 1177 send an e-mail to [email protected]"

for match in phonenumbers.PhoneNumberMatcher(text_block, "GB"):
    print(match)

This would output:

PhoneNumberMatch [130,145) +44-7986-123456
PhoneNumberMatch [149,162) 020 8366 1177

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

Even though the phone numbers are embedded deep into the text with a variety of formats with other numbers, PhoneNumberMatcher successfully returns the phone numbers with great accuracy.

Apart from extracting data from the text, we might also want to get the digits one by one from the user. Imagine that your app’s UI works similar to modern mobile phones, and formats the phone numbers as you type in. For instance, on your web page, you might want to pass the data to your API with each onkeyup event and use AsYouTypeFormatter() to format the phone number with each incoming digit.

Since UI part is out of the scope of this article, we’ll use a basic example for AsYouTypeFormatter. To simulate on-the-fly formatting, let’s jump into the Python interpreter:

>>> import phonenumbers
>>> formatter = phonenumbers.AsYouTypeFormatter("TR")
>>> formatter.input_digit("3")
'3'
>>> formatter.input_digit("9")
'39'
>>> formatter.input_digit("2")
'392'
>>> formatter.input_digit("2")
'392 2'
>>> formatter.input_digit("2")
'392 22'
>>> formatter.input_digit("1")
'392 221'
>>> formatter.input_digit("2")
'392 221 2'
>>> formatter.input_digit("3")
'392 221 23'
>>> formatter.input_digit("4")
'392 221 23 4'
>>> formatter.input_digit("5")
'392 221 23 45'

Not all user input happens as they type. Some forms have simple text input fields for phone numbers. However, that doesn’t necessarily mean that we’ll have data entered in a standard format.

The Phonenumbers library got us covered here too with the format_number() method. This method allows us to format phone numbers into three well-known, standardized formats. National, International, and E164. National and International formats are pretty self-explanatory, while the E164 format is an international phone number format that ensures phone numbers are limited with 15 digits and are formatted {+}{country code}{number with area code}. For more information on E164, you can check this Wikipedia page.

Let’s start with the national formatting:

import phonenumbers

my_number = phonenumbers.parse("+40721234567")
national_f = phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.NATIONAL)
print(national_f)

This will return a nicely spaced phone number string with the national format:

0721 234 567

Now let’s try to format the national number as in international format:

import phonenumbers

my_number = phonenumbers.parse("0721234567", "RO")  # "RO" is ISO Alpha-2 code for Romania
international_f = phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
print(international_f)

The above code will return a nicely spaced phone number string:

+40 721 234 567

Notice that we passed "RO" as the second parameter into the parse() method. Since the input number is a national number, it has no country code prefix to hint at the country. In these cases, we need to specify the country with its ISO Alpha-2 code to get an accurate result. Excluding either the numeric and ISO Alpha-2 country codes, will cause an exception of NumberParseException: (0) Missing or invalid default region..

Now let’s try the E164 formatting option. We’ll pass a national string as the input:

import phonenumbers

my_number = phonenumbers.parse("0721234567", "RO")
e164_f=phonenumbers.format_number(my_number, phonenumbers.PhoneNumberFormat.E164)
print(e164_f)

The output will be very similar to the PhoneNumberFormat.INTERNATIONAL, except with the spaces:

+40721234567

This is very useful when you want to pass the number to a background API. It isn’t uncommon for APIs to expect phone numbers to be non-spaced strings.

Get Additional Information on Phone Number

A phone number is loaded with data about a user that could be of interest to you. You may want to use different APIs or API endpoints depending on the carrier of the particular phone number since this plays a role in the product cost. You might want to send your promotion notifications depending on your customer’s (phone number’s) timezone so that you don’t send them a message in the middle of the night. Or you might want to get information about the phone number’s location so that you can provide relevant information. The Phonenumbers library provides the necessary tools to fulfill these needs.

To start with the location, we will use the description_for_number() method from the geocoder class. This method takes in a parsed phone number and a short language name as parameters.

Let’s try this with our previous fake number:

import phonenumbers
from phonenumbers import geocoder

my_number = phonenumbers.parse("+447986123456")
print(geocoder.description_for_number(my_number, "en"))

This will print out the origin country of the phone number:

United Kingdom

Short language names are pretty intuitive. Let’s try to get output in Russian:

import phonenumbers
from phonenumbers import geocoder

my_number = phonenumbers.parse("+447986123456")
print(geocoder.description_for_number(my_number, "ru"))

And here’s the output which says the United Kingdom in Russian:

Соединенное Королевство

You can try it out with other languages of your preferences like «de», «fr», «zh», etc.

As mentioned before, you might want to group your phone numbers by their carriers, since in most cases it will have an impact on the cost. To clarify, the Phonenumbers library probably will provide most of the carrier names accurately, but not 100%.

Today in most countries it is possible to get your number from one carrier and later on move the same number to a different carrier, leaving the phone number exactly the same. Since Phonenumbers is merely an offline Python library, it is not possible to detect these changes. So it’s best to approach the carrier names as a reference, rather than a fact.

We will use the name_for_number() method from carrier class:

import phonenumbers
from phonenumbers import carrier

my_number = phonenumbers.parse("+40721234567")
print(carrier.name_for_number(my_number, "en"))

This will display the original carrier of the phone number if possible:

Vodafone

Note: As it is mentioned in the original documents of the Python Phonenumbers, carrier information is available for mobile numbers in some countries, not all.

Another important piece of information about a phone number is its timezone. The time_zones_for_number() method will return a list of timezones that the number belongs to. We’ll import it from phonenumbers.timezone :

import phonenumbers
from phonenumbers import timezone

my_number = phonenumbers.parse("+447986123456")
print(timezone.time_zones_for_number(my_number))

This will print the following timezones:

('Europe/Guernsey', 'Europe/Isle_of_Man', 'Europe/Jersey', 'Europe/London')

This concludes our tutorial on Python Phonenumbers.

Conclusion

We learned how to parse phone numbers with parse() method, extract numbers from text blocks with PhoneNumberMatcher(), get the phone numbers digit by digit and format it with AsYouTypeFormatter(), use different validation methods with is_possible_number() and is_possible_number(), format numbers using NATIONAL, INTERNATIONAL, and E164 formatting methods, and extract additional information from the phone numbers using geocoder, carrier, and timezone classes.

Remember to check out the original GitHub repo of the Phonenumbers library. Also if you have any questions in mind, feel free to comment below.

Кодинг-марафон. Задача 6.

В БД некоего предприятия номера телефонов хранятся как попало и вам поручили написать функцию, которая приведёт их все к одному формату.

Функция должна называться format_numbers, она принимает на вход строку (исходный номер) и возвращает строку (номер в нужном формате).

Сигнатура def format_numbers(phone_number: str) -> str:

Особенности номеров в БД:

  • помимо цифр может содержать дефисы -, пробелы, скобки и знак + (но + только первым символом)
  • номер всегда валиден (содержит 11 цифр)
  • номер всегда начинается с 8 или +7, причем + может быть только в начале номера
  • не может быть 2 идущих подряд дефисов, скобок или пробелов

Необходимо, чтобы на выходе любой номер стал такого формата: +7(909)101-10-10

Примеры

format_numbers('+79091011010') == '+7(909)101-10-10'
format_numbers('8(909)1011010') == '+7(909)101-10-10'
format_numbers('+7 909 101-10-10') == '+7(909)101-10-10'

Варианты решений

def format_numbers(phone_number: str) -> str:
    return '+7({0}{1}{2}){3}{4}{5}-{6}{7}-{8}{9}'.format(*[i for i in phone_number if i.isdigit()][1:])
def format_numbers(phone_number: str) -> str:
    numbers = list(filter(str.isdigit, phone_number))[1:]
    return "+7({}{}{}){}{}{}-{}{}-{}{}".format(*numbers)

Время прочтения
3 мин

Просмотры 29K

В процессе изучения Python стало интересно попробовать его в связке с API VK. В ВК есть телефонная книга, она показывает телефоны ваших друзей в более-менее удобном формате. Так как далеко не всегда люди охотно оставляют там полые(валидные) номера своих телефонов, мне показалась интересной идея написать скрипт, который отбирал бы только валидные номера моб.телефонов и выдавал бы их отдельной таблицей. Наша телефонная книга будет генерировать csv-файл, который затем можно будет открыть, например, в excel.

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

import vk
from time import sleep
from re import sub, findall
from getpass import getpass
from csv import writer, QUOTE_ALL

Создадим класс User с необходимыми методами:

class User(object):
	"""VK User"""
	def __init__(self, login, password):
		self.login = login
		self.password = password
		self.id = ''
	# аторизирует юзера
	def auth(self):
		session = vk.AuthSession(app_id='5340228', user_login=self.login, user_password=self.password)
		api = vk.API(session)
		return api
	# возвращает массив объектов друзей
	def friends(self, api):
                # возвращает в том порядке, в котором расположены в разделе Мои
		user_friends = api.friends.get(user_id=self.id, order='hints')
		return user_friends
	# возвращает количество друзей
	def friends_count(self, api):
		user_friends = User.friends(self, api)
		friends_count = len(user_friends)
		return friends_count
	# возвращает массив данных о юзере
	def info(self, api):
		user = api.users.get(user_id=self.id)
		return user[0]

Долго не мог решить проблему, и в гугле как-то не попадалось на глаза, как взять id текущего пользователя. По счастливой случайности нашел выход — надо передать в качестве аргумента пустую строку.

Далее напишем функцию валидатор, которая будет приводить мобильные номера к общему виду. Мне, как жителю Украины, интересно выбирать только украинские моб.номера, которые должны начинаться на «0». Скрипт легко подправить под любой формат.

def norm_mob(str):
	if len(str) != '':
		norm_mob = sub(r'(s+)?[+]?[-]?', '', str)
		# проверяем строку на наличие в ней только необходимых символов
		right_mob = findall(r'[d]', norm_mob)
		# если количество знаков в двух строках совпадает, значит это номер телефона
		if (len(right_mob) == len(norm_mob)) and (len(norm_mob) >= 10):
			rev_norm_mob = norm_mob[::-1]
			norm_mob = rev_norm_mob[0:10]
			if norm_mob[::-1][0] == '0':
				return norm_mob[::-1]
	else:
		return False

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

def find_correct_phone_numbers(api, friends, friends_count):
	users_phones = []
	for i in range(0, friends_count):
		cur_user_id = int(friends[i])
		cur_user = api.users.get(user_id=cur_user_id, fields='contacts')
		try:
			# выбираем номер мобильного телефона
			cur_mob = cur_user[0]['mobile_phone']
		except KeyError:
			sleep(0.3)
			continue
		mob = norm_mob(cur_mob)
		if mob:
			# вставим еще одну строку в наш массив
			users_phones.append({
				'user_name': '{} {}'.format(cur_user[0]['first_name'], cur_user[0]['last_name']),
				'user_phone': '8{}'.format(mob)
				})
		sleep(0.4)
	return users_phones

Сохраняем полученный результат.

def saveCSV(data, path):
    with open(path, 'w') as csvfile:
        my_writer = writer(csvfile, delimiter='	', quotechar='"', quoting=QUOTE_ALL)
        my_writer.writerow(('Имя пользователя', 'Номер моб. телефона'))
        for item in data:
        	try:
        		my_writer.writerow((item['user_name'], item['user_phone']))
        	except Exception:
        		my_writer.writerow(('(Ошибка в кодировке)', item['user_phone']))

Добавим функцию, которая считала бы затраченное время.

class Timer(object):
    def __enter__(self):
        self._startTime = time()
    def __exit__(self, type, value, traceback):
    	howLong = time() - self._startTime
    	print("Операция заняла: {:.2f} минут".format(howLong/60))

Ну и заключительный этап, сделаем вызов написанных функций.

def main():
	while True:
		login = input('E-mail: ')
		password = getpass('Password: ')
		try:
			vk_user = User(login, password)
			api = vk_user.auth()
			print('Авторизация выполнена успешно!')
			break
		except Exception:
			print('Вы ввели неверные данные, пожалуйста, повторите попытку.')
	friends = vk_user.friends(api)
	friends_count = vk_user.friends_count(api)
	print('Найдено {} друзей.'.format(friends_count))
	print('Идет выборка мобильных номеров...')
	with Timer() as p:
		users_phones = find_correct_phone_numbers(api, friends, friends_count)
	print('Выборка окончена. Сохранение...')
	saveCSV(users_phones, 'vk_mob.csv')
	print('Данные успешно сохранены.')
if __name__ == '__main__':
	main()

На выходе получаем csv-файл, который можно открыть в excel в формате удобной таблицы.

Задача

Создать телефонный справочник с возможностью импорта и экспорта данных в нескольких форматах. Под форматами понимаем структуру файлов, например, в файле на одной строке хранится одна часть записи, пустая строка — разделитель

Фамилия_1

Имя_1

Телефон_1

Описание_1

Фамилия_2

Имя_2

Телефон_2

Описание_2

и т.д.

В файле на одной строке хранится все записи, символ разделитель — ;

Фамилия_1;Имя_1;Телефон_1;Описание_1

Фамилия_2;Имя_2;Телефон_2;Описание_2

и т.д.

Решение

Структура проекта состоит из 4 модулей:

  • User_interface. Предоставляет пользователю возможность ввести данные для дальнейшого сохранения в телефонном справочнике. В данном модюле присутствует проверка на количество символов в номере телефона, и проверка на число.
    Все четыре категории данных, а именно фамилия, имя, номер телефона и описание, сохраняются в списке info.
  • CSV_creating. Модуль создает файл .csv и записывает в него шапку таблицы.
  • File_writing. Содержит два метода для записи файла csv и .txt. В первом данные сохраняются через ‘;‘, во втором — через пустую строку части записи, и через две пустые строки целые записи.
    +Main. Проверяет существует ли файл с расширением .csv. Если нет, то запускает модуль создания файла с шапкой таблицы. После этого вызываюся модуль записи, который в свою очередь забирает информацию из UI.

In this tutorial, we’ll look at how to get phone number information in Python. The name ‘phonenumbers’ refers to an extremely fascinating and handy library. And that’s the library that will help us have some fun with Phone numbers in Python.

We will be utilizing the phonenumbers library to obtain information about a phone number. Let’s go deeper into this lesson to learn more about it.

To begin, run the following line on your command prompt to install the phonenumbers library.


Convert String to phonenumber format

To investigate the functionalities of the phonenumbers module, we must first obtain a user’s phone number in phonenumber format. In this section, we’ll look at how to convert a user’s phone number to phonenumber format.

The input must be of the string type, and the country code must come before the phone number.

import phonenumbers
pN = phonenumbers.parse("+919876643290")
print(pN)
Country Code: 91 National Number: 9876643290

Get Timezone

Here is a simple Python program that uses the phonenumbers module to determine the timezone of a phone number.

First, we convert the string input to phone number format, and then we utilize an inbuilt method to determine a user’s timezone. It only returns results for valid numbers.

import phonenumbers
from phonenumbers import timezone
pN = phonenumbers.parse("+919876643290")
tZ = timezone.time_zones_for_number(pN)
print(tZ)

Extract phone numbers from text

Using this module, we can extract phone numbers from text/paragraphs. You may iterate through it to get a list of phone numbers. The PhoneNumberMatcher object offers the necessary method for this.

import phonenumbers
T = "Contact us at +919876643290 or +14691674587"
N = phonenumbers.PhoneNumberMatcher(T, "IN")
for n in N:
	print(n)
PhoneNumberMatch [14,27) +919876643290

Carrier and Region of a Phone Number

We will learn how to use the geocoder and carrier functionalities of this module to determine the carrier and area of a phone number.

import phonenumbers
from phonenumbers import geocoder, carrier
pN = phonenumbers.parse("+919876643290")
C = carrier.name_for_number(pN, 'en')
R = geocoder.description_for_number(pN, 'en')
print(C)
print(R)

Conclusion

Congratulations! You just learned how to get Phone Number Information in Python. Hope you enjoyed it! 😇

Liked the tutorial? In any case, I would recommend you to have a look at the tutorials mentioned below:

  1. Python: Convert Number to Words
  2. Convert a number to words [digit by digit] in Python
  3. 3 Easy Methods to Find the Smallest Number in Python

Thank you for taking your time out! Hope you learned something new!! 😄


Понравилась статья? Поделить с друзьями:
  • Номера телефонов бтс настоящие на русском языке
  • Номера телефонов военкоматов спб
  • Номера телефонов бсмп витебск
  • Номера телефонов брестский вагонный участок
  • Номера телефонов борисов автовокзал