Создание классов и объектов

Defining a Class in Python

Like function definitions begin with the keyword in Python, class definitions begin with a keyword.

The first string inside the class is called docstring and has a brief description about the class. Although not mandatory, this is highly recommended.

Here is a simple class definition.

A class creates a new local namespace where all its attributes are defined. Attributes may be data or functions.

There are also special attributes in it that begins with double underscores . For example, gives us the docstring of that class.

As soon as we define a class, a new class object is created with the same name. This class object allows us to access the different attributes as well as to instantiate new objects of that class.

Output

10
<function Person.greet at 0x7fc78c6e8160>
This is a person class

deque

В соответствии с документацией Python, deque – это обобщение стеков и очередей. Они являются контейнером замен для списка Python. Они защищены от потоков и поддерживают эффективность соединения памяти, а также сноски с обеих сторон deque. Список оптимизирован под быстрые операции с фиксированной длиной. За всеми подробностями можете обратиться к . Наш deque поддерживает аргумент maxlen, который устанавливает границы для deque. В противном случае deque будет расти до произвольных размеров. Когда ограниченный deque заполнен, любые новые объекты, которые были добавлены, вызовут такое же количество элементов, которые выскочат с другого конца. Вот основное правило: если вам нужно что-то быстро дописать или вытащить, используйте deque. Если вам нужен быстрый случайный доступ, используйте list. Давайте уделим пару минут, и посмотрим, как мы можем создавать и использовать deque.

Python

from collections import deque
import string

d = deque(string.ascii_lowercase)
for letter in d:
print(letter)

1
2
3
4
5
6

fromcollectionsimportdeque

importstring

d=deque(string.ascii_lowercase)

forletter ind

print(letter)

Здесь мы импортируем deque из нашего модуля collections, а также модуль string. Для того, чтобы создать экземпляр deque, нам нужно передать его итерируемой. В данном случае, мы передали его string.ascii_lowercase, и получили список всех строчных букв в алфавите. Наконец, мы сделали цикл над deque и вывели каждый объект. Теперь давайте взглянем на несколько методов, которыми обладает deque.

Python

d.append(‘bork’)
print(d)

# deque()

d.appendleft(‘test’)
print(d)

# deque()

d.rotate(1)
print(d)

# deque()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

d.append(‘bork’)

print(d)

 
# deque()
 

d.appendleft(‘test’)

print(d)

 
# deque()
 

d.rotate(1)

print(d)

 
# deque()

Давайте устроим небольшой разбор полетов. Сначала мы разместили строку в правом краю deque. Далее разместили другую строку в левом краю deque. Наконец, мы вызываем rotate в нашем deque и передаем его единице, что заставляет его сместиться один раз в право. Другими словами, это заставляет один объект сместиться с правой части на фронтальную. Вы можете передать ему отрицательное число, чтобы происходило то же самое, но с левой стороны. Давайте закончим этот раздел и взглянем на пример, основанный на документации Python:

Python

from collections import deque

def get_last(filename, n=5):
«»»
Возвращаем последние N кол-во строк из файла
«»»
try:
with open(filename) as f:
return deque(f, n)
except OSError:
print(«Файл не открывается: {}».format(filename))
raise

1
2
3
4
5
6
7
8
9
10
11
12
13

fromcollectionsimportdeque

defget_last(filename,n=5)

«»»

    Возвращаем последние N кол-во строк из файла
    «»»

try

withopen(filename)asf

returndeque(f,n)

exceptOSError

print(«Файл не открывается: {}».format(filename))

raise

Этот код работает по схожему принципу с программой-хвостом Linux. Здесь мы передаем имя файла нашему скрипту вместе с n количеством строк, которые мы хотим вернуть. Наш deque ограничен той или иной цифрой, которую мы указываем как n. Это значит, что как только deque заполнится, когда новые строки прочитаны и добавлены в deque, старые строки выпадают из другого конца и отбрасываются. Я также завернул открываемый в операторе файл в простой обработчик исключений, так как очень легко выполнить передачу по неверному пути. Таким образом, мы поймаем несуществующие файлы, к примеру. Теперь мы готовы идти дальше и приступить к изучению namedtuple.

OrderedDict

Модуль Python collections имеет еще один замечательный наследуемый класс dict под названием OrderedDict. Как подразумевается в его названии, этот словарь отслеживает порядок ключей после их добавления. Если вы создадите обычный dict, вы заметите, что данные в нем неупорядоченные:

Python

d = {‘banana’: 3, ‘apple’:4, ‘pear’: 1, ‘orange’: 2}
print(d)
# {‘apple’: 4, ‘banana’: 3, ‘orange’: 2, ‘pear’: 1}

1
2
3

d={‘banana’3,’apple’4,’pear’1,’orange’2}

print(d)

# {‘apple’: 4, ‘banana’: 3, ‘orange’: 2, ‘pear’: 1}

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

Python

d = {‘banana’: 3, ‘apple’:4, ‘pear’: 1, ‘orange’: 2}

keys = d.keys()
keys = sorted(keys)

for key in keys:
print (key, d)

1
2
3
4
5
6
7

d={‘banana’3,’apple’4,’pear’1,’orange’2}

keys=d.keys()

keys=sorted(keys)

forkey inkeys

print(key,dkey)

Результат

Python

apple 4
banana 3
orange 2
pear 1

1
2
3
4

apple4

banana3

orange2

pear1

Давайте создадим экземпляр OrderedDict, используя оригинал dict, но на этапе создания мы отсортируем ключи в этом словаре:

Python

from collections import OrderedDict

d = {‘banana’: 3, ‘apple’:4, ‘pear’: 1, ‘orange’: 2}
new_d = OrderedDict(sorted(d.items()))

print(new_d)
# OrderedDict()

for key in new_d:
print (key, new_d)

1
2
3
4
5
6
7
8
9
10

fromcollectionsimportOrderedDict

d={‘banana’3,’apple’4,’pear’1,’orange’2}

new_d=OrderedDict(sorted(d.items()))

print(new_d)

# OrderedDict()
 

forkey innew_d

print(key,new_dkey)

Результат

Python

apple 4
banana 3
orange 2
pear 1

1
2
3
4

apple4

banana3

orange2

pear1

Здесь мы создали наш OrderedDict, сортируя его при помощи встроенной функции Python sorted. Функция sorted берет объекты словаря, который является списком кортежей, отображающих пары ключей словаря. Данная функция сортирует их, затем передает в OrderedDict, который сохраняет указанный порядок. Таким образом, когда мы выводим ключи и значения, они будут в том порядке, который мы и ожидаем. Если вы создадите цикл над обычным словарем (с неотсортированным списком ключей), порядок будет меняться каждый раз

Обратите внимание на то, что если вы добавляете новые ключи, они будут расположены в конце OrderedDict, без автоматической сортировки. Также стоит отметить, что когда вы сравниваете два OrderedDicts, они не только будут тестировать объекты на равенство, но также на то, корректен ли указанный порядок

Обычный словарь только смотрит на содержимое словаря, не обращая никакого внимание на порядок этого содержимого. Наконец, OrderedDicts содержит два новых метода в Python 3: popitem и move_to_end.

  • Метод popitem возвращает и удаляет пары (ключей или объектов).
  • Метод move_to_end двигает существующий ключ в любой конец OrderedDict. Объект будет смещен в правый угол, если последний аргумент OrderedDict указан как True (это по умолчанию), или в начало, если он указан как False.

Любопытно, но OrderedDicts поддерживает обратную итерацию, используя встроенную функцию reversed:

Python

for key in reversed(new_d):
print (key, new_d)

1
2

forkey inreversed(new_d)

print(key,new_dkey)

Результат

Python

pear 1
orange 2
banana 3
apple 4

1
2
3
4

pear1

orange2

banana3

apple4

Весьма точно, однако, вероятно вам такой функционал не понадобится.

Давайте посмотрим, как все это работает!

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

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

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

Вот что происходит при вызове метода
экземпляра класса:

>>> obj = MyClass()
>>> obj.method()
('instance method called', <MyClass instance at 0x101a2f4c8>)

Мы видим, что method (т. е., метод
экземпляра класса) имеет доступ к
экземпляру объекта (это видно по выводу
<MyClass instance>) при помощи аргумента
self.

При вызове этого метода Python замещает
аргумент self экземпляром объекта (obj). Мы
можем проигнорировать синтаксический
сахар dot-call синтаксиса (obj.method()) и получить
тот же результат, передав экземпляр
объекта вручную:

>>> MyClass.method(obj)
('instance method called', <MyClass instance at 0x101a2f4c8>)

Можете догадаться, что произойдет,
если вы попытаетесь вызвать этот метод
без первоначального создания экземпляра
класса?

Кстати, методы экземпляра класса при
помощи атрибута self.__class__ также могут
иметь доступ и к самому классу. Это
делает данные методы особенно полезными
в условиях ограничений доступа: они
могут изменять состояние экземпляра
объекта и самого класса.

Теперь давайте испытаем метод класса:

>>> obj.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

Вызов classmethod() показал, что этот метод
не имеет доступа к объекту <MyClass
instance>. Но у него есть доступ к объекту
<class MyClass>, который представляет сам
класс (в Python вообще все является объектом,
даже классы).

Стоит отметить, что при вызове
MyClass.classmethod() Python автоматически передает
класс в качестве первого аргумента
функции. Это поведение Python запускается,
если метод вызывается при помощи
dot-синтаксиса. В методах экземпляра
класса аналогично работает параметр
self.

Пожалуйста, обратите внимание, что
эти параметры именуются self и cls лишь в
силу соглашений. С тем же успехом вы
можете назвать их the_object и the_class

Важно
то, что они идут первыми в списке
параметров метода. А теперь давайте вызовем статический
метод:

А теперь давайте вызовем статический
метод:

>>> obj.staticmethod()
'static method called'

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

Просто когда при вызове статического
метода с использованием dot-синтаксиса
не передаются аргументы self или cls, Python
применяет ограничения доступа.

Этот пример подтверждает, что статические
методы не имеют доступа ни к состоянию
экземпляра объекта, ни к состоянию
класса. Они работают как обычные функции,
но при этом относятся к пространству
имен класса (и каждого его экземпляра).

Теперь давайте посмотрим, что произойдет,
если мы попытаемся вызвать эти методы
в самом классе, т. е., без предварительного
создания экземпляра объекта:

>>> MyClass.classmethod()
('class method called', <class MyClass at 0x101a2f4c8>)

>>> MyClass.staticmethod()
'static method called'

>>> MyClass.method()
TypeError: unbound method method() must
    be called with MyClass instance as first
    argument (got nothing instead)

Нам прекрасно удалось вызвать
classmethod() и staticmethod() , но попытка вызвать
метод экземпляра класса method() провалилась
(TypeError).

Этого и следовало ожидать: в этот раз
мы не создавали экземпляр объекта и
попытались вызвать функцию экземпляра
класса прямо из самого класса. Это
означает, что у Python не было никакой
возможности заполнить аргумент self и,
как следствие этого, вызов метода
провалился.

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

Мои примеры будут основаны на классе
Pizza:

class Pizza:
    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients!r})'

>>> Pizza()
Pizza()

Примечание. В этом примере кода
(а также в последующих) для форматирования
строки, возвращаемой при помощи __repr__,
мы будем использовать Python
3.6 f-strings. В Python 2 и версиях Python 3 до 3.6
для форматирования строки следует
использовать другие выражения, например:

def __repr__(self):
    return 'Pizza(%r)' % self.ingredients

Вызов исключений в разных версиях Python

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

Python 2

Python

print ‘Python’, python_version()

1 print’Python’,python_version()

Shell

Python 2.7.6

1 Python2.7.6

Python

raise IOError, «file error»

1 raiseIOError,»file error»

Shell

—————————————————————————
IOError Traceback (most recent call last)

<ipython-input-8-25f049caebb0> in <module>()
—-> 1 raise IOError, «file error»

IOError: file error

1
2
3
4
5
6
7
8

—————————————————————————

IOError                                   Traceback(most recent call last)

<ipython-input-8-25f049caebb0>in<module>()

—->1raise IOError,»file error»

IOErrorfileerror

Python

raise IOError(«file error»)

1 raiseIOError(«file error»)

Shell

—————————————————————————
IOError Traceback (most recent call last)

<ipython-input-9-6f1c43f525b2> in <module>()
—-> 1 raise IOError(«file error»)

IOError: file error

1
2
3
4
5
6
7
8

—————————————————————————

IOError                                   Traceback(most recent call last)

<ipython-input-9-6f1c43f525b2>in<module>()

—->1raise IOError(«file error»)

IOErrorfileerror

Python 3

Python

print(‘Python’, python_version())

1 print(‘Python’,python_version())

Shell

Python 3.8.1

1 Python3.8.1

Python

raise IOError, «file error»

1 raiseIOError,»file error»

Shell

File «<ipython-input-10-25f049caebb0>», line 1
raise IOError, «file error»
^
SyntaxError: invalid syntax

1
2
3
4

File»<ipython-input-10-25f049caebb0>»,line1

raise IOError,»file error»

^

SyntaxErrorinvalid syntax

Правильный способ поднятия исключения в Python 3:

Python

print(‘Python’, python_version())
raise IOError(«file error»)

1
2

print(‘Python’,python_version())

raiseIOError(«file error»)

Shell

Python 3.4.1

—————————————————————————
OSError Traceback (most recent call last)

<ipython-input-11-c350544d15da> in <module>()
1 print(‘Python’, python_version())
—-> 2 raise IOError(«file error»)

OSError: file error

1
2
3
4
5
6
7
8
9
10
11
12
13

Python3.4.1

—————————————————————————

OSError                                   Traceback(most recent call last)

<ipython-input-11-c350544d15da>in<module>()

1print(‘Python’,python_version())

—->2raise IOError(«file error»)

OSErrorfileerror

Объекты

Объект – это экземпляр класса. Используйте класс Shark для создания объекта jimmy.

Вы инициализировали объект jimmy как экземпляр класса.

Теперь добавьте методы класса Shark в объект jimmy:

Теперь объект jimmy, созданный на основе класса Shark, использует методы swim() и be_awesome(), которые были вызваны с помощью оператора-точки. Этот оператор позволяет сослаться на атрибут объекта.  В этом случае атрибут является методом, и он вызывается со скобками, как любая обычная функция.

Поскольку ключевое слово self является параметром методов, как определено в классе Shark, объект jimmy передается методам. Параметр self позволяет методам ссылаться на атрибуты объекта.

При вызове методов объект jimmy автоматически передается с помощью оператора-точки.

Добавьте объект в файл shark.py:

Запустите программу:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector