Отладка
Это самая важная вещь для глубокого изучения и понимания конкретного языка. Разработчик должен понимать, как работает код, как реализована библиотека, используя инструмент отладки для проверки вызова функции, переменных и логики.
>>> def hanoi_population(list_populations): import pdb; pdb.set_trace() big_city_populations = [population for population in list_populations if population > 1000] return round(sum(big_city_populations), 2) >>> hanoi_population([10000, 20000, 100]) > <ipython-input-7-1e8b6f117387>(3)hanoi_population() -> big_city_populations = [population for population in list_populations if population > 1000] (Pdb) h Documented commands (type help <topic>): ======================================== EOF bt cont enable jump pp run unt a c continue exit l q s until alias cl d h list quit step up args clear debug help n r tbreak w b commands disable ignore next restart u whatis break condition down j p return unalias where Miscellaneous help topics: ========================== exec pdb Undocumented commands: ====================== retval rv
Показать все команды, нажав h или help после (Pdb)
- Одной из любимых команд для отладки является команда DIR (показывает все атрибуты и методы, связанные с объектом).
>>> numbers = [1, 2, 3, 4, 1, 2] >>> dir(numbers) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
*args и **kwargs
Эти списки аргументов не распространены в вашем коде, но они часто используются в библиотеке и фреймворке.
1. *аргументы
- список аргументов (пример: 1, «привет, Джо», объект, 1.23)
- Как получить содержимое *args: доступ по индексу (например: args[0], args[1])
>>> def print_my_arguments(*args): for arg in args: print arg >>> print_my_arguments(1, 'Hello Joe', 3) 1 Hello Joe 3
2. **кварг
- аргументы с ключевыми словами (пример: message='Hello Joe', is_developer=True, member=member_object)
- Как получить содержимое **kwargs: kwargs работает как dict (например: kwargs.get(‘message’) или kwargs[‘message’]
>>> def print_my_keyworded_arguments(**kwargs): for key, value in kwargs.items(): print key, ":", value >>> print_my_keyworded_arguments(message='Hello Joe', age=27) message : Hello Joe age : 27
3. Использование как *args, так и **kwargs
- В основном *args и **kwargs используются для декораторов функций.
- Обезьянье исправление (используемое для изменения некоторого кода во время выполнения) также является хорошим способом использования этого
- Если вы хотите иметь достаточную гибкость для аргументов вашей функции (как список аргументов, так и аргументы с ключевыми словами)
Словарь
Это мой любимый трюк, словарь мощный и простой в использовании
- Если слишком много предложений if/else =› с использованием словаря
- Если для ключа должно быть значение по умолчанию => используйте setdefault
>>> def count_duplicates(numbers): result = {} for number in numbers: if number not in result: # No need for if here result[key] = 0 result[number] += 1 return result We can rewrite the function with setdefault >>> def count_duplicates(numbers): result = {} for number in numbers: result.setdefault(number, 0) # this is clearer result[number] += 1 return result
- Словарь для списка: items()
>>> a_dict = {'a': 1, 'b': 2} >>> a_dict.items() [('a', 1), ('b', 2)]
- Список в словарь
>>> a_list = [['a', 1], ['b', 2], ['c', 3]] >>> dict(a_list) {'a': 1, 'b': 2, 'c': 3}
- Инвертирующий словарь
>>> a_dict = {'a': 1, 'b': 2, 'c': 3} >>> invert_a_dict = {v: k for k, v in a_dict.iteritems()} >>> invert_a_dict {1: 'a', 2: 'b', 3: 'c'}
- Избегайте KeyError в словаре => Использование defaultdict коллекций
>>> a_dict = {'a': 1} >>> a_dict['b'] KeyError: 'b' >>> from collections import defaultdict >>> a_default_dict = defaultdict(list) >>> a_default_dict['a'] [] >>> from collections import defaultdict >>> a_default_dict
Функция
- Каждый раз, когда вы обнаружите, что постоянно пишете один и тот же/похожий код, вы слишком много работаете => используйте функцию шаблона.
- Функция-оболочка (и декораторы) — один из лучших фокусов
>>> def update_phone_number(member, phone): member.phone = phone member.save() This is a simple function that update the phone number for a member. However, I realise that * I want to check if them member has permission to change phone or not * and I also want to keep the permission function out of my method above. @permission def update_phone_number(member, phone): member.phone = phone member.save() def permission(func): def validate(*args, **kwargs): if not member.has_permission() raise Exception('Not permitted to change phone') return func(*args, **kwargs) return validate
Модульный тест
- Напишите модульный тест для успеха/неудачи/исключения, чтобы убедиться, что ваша программа работает правильно, как и ожидалось.
- Пример: сохраните содержимое в файл с именем test_python.py и запустите python test_python.py на терминале.
import unittest def crease_one(x): return x + 1 class MyTest(unittest.TestCase): def test(self): self.assertEqual(increase_one(3), 4) if __name__ == '__main__': unittest.main()
Подборки
- Это полезный пакет Python, который мы могли бы часто использовать.
- defaultdict/deque/namedtuple/counter/OrderedDict
>>> from collections import Counter >>> numbers = [1, 2, 3, 4, 1, 2] >>> counter = Counter(number for number in numbers) >>> print counter Counter({1: 2, 2: 2, 3: 1, 4: 1})