Создание новых объектов с использованием класса

PythonPythonBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом разделе介绍了类声明和创建新对象的概念。

Объектно-ориентированное (OO) программирование

Техника программирования, при которой код организован в виде коллекции объектов.

Объект состоит из:

  • Данных. Атрибуты
  • Поведения. Методы, которые представляют собой функции, применяемые к объекту.

Вы уже использовали некоторое ОО в рамках этого курса.

Например, манипуляция списком.

>>> nums = [1, 2, 3]
>>> nums.append(4)      ## Метод
>>> nums.insert(1,10)   ## Метод
>>> nums
[1, 10, 2, 3, 4]        ## Данные
>>>

nums является экземпляром списка.

Методы (append() и insert()) прикреплены к экземпляру (nums).

Ключевое слово class

Используйте ключевое слово class для определения нового объекта.

class Player:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.health = 100

    def move(self, dx, dy):
        self.x += dx
        self.y += dy

    def damage(self, pts):
        self.health -= pts

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

Экземпляры

Экземпляры - это фактические объекты, с которыми вы работаете в своем программе.

Они создаются путем вызова класса в качестве функции.

>>> a = Player(2, 3)
>>> b = Player(10, 20)
>>>

a и b - это экземпляры класса Player.

Подчеркните: Класс - это только определение (сам по себе он ничего не делает). Аналогично определению функции.

Экземплярные данные

Каждый экземпляр имеет свои собственные локальные данные.

>>> a.x
2
>>> b.x
10

Эти данные инициализируются методом __init__().

class Player:
    def __init__(self, x, y):
        ## Любое значение, хранимое в `self`, является экземплярным данными
        self.x = x
        self.y = y
        self.health = 100

Не существует ограничений на общее количество или тип хранимых атрибутов.

Экземплярные методы

Экземплярные методы - это функции, применяемые к экземплярам объекта.

class Player:
  ...
    ## `move` - это метод
    def move(self, dx, dy):
        self.x += dx
        self.y += dy

Объект сам по себе всегда передается в качестве первого аргумента.

>>> a.move(1, 2)

## сопоставляет `a` с `self`
## сопоставляет `1` с `dx`
## сопоставляет `2` с `dy`
def move(self, dx, dy):

По соглашению экземпляр называется self. Однако, на самом деле имя, которое используется, не имеет значения. Объект всегда передается в качестве первого аргумента. Просто по стилям программирования на Python этот аргумент называется self.

Области видимости классов

Классы не определяют область видимости имен.

class Player:
 ...
    def move(self, dx, dy):
        self.x += dx
        self.y += dy

    def left(self, amt):
        move(-amt, 0)       ## Нет. Вызывает глобальную функцию `move`
        self.move(-amt, 0)  ## Да. Вызывает метод `move` из вышеуказанного.

Если вы хотите выполнять операции с экземпляром, вы всегда явно ссылаетесь на него (например, self).

Начиная с этой серии упражнений, мы начинаем вносить一系列 изменения в существующий код из предыдущих разделов. Важно, чтобы у вас был рабочий вариант упражнения 3.18 для начала. Если у вас его нет, пожалуйста, работайте по коду решения, найденному в директории Solutions/3_18. Можно скопировать его.

Упражнение 4.1: Объекты в качестве структур данных

В разделах 2 и 3 мы работали с данными, представленными в виде кортежей и словарей. Например, позиция в акциях может быть представлена в виде кортежа так:

s = ('GOOG',100,490.10)

или в виде словаря так:

s = { 'name'   : 'GOOG',
    'shares' : 100,
     'price'  : 490.10
}

Вы даже можете писать функции для манипуляции такими данными. Например:

def cost(s):
    return s['shares'] * s['price']

Однако, при расширении вашей программы вы, возможно, захотите создать более четкую структуру. Таким образом, другой подход к представлению данных - определить класс. Создайте файл под названием stock.py и определите класс Stock, представляющий собой одну позицию в акциях. Пусть экземпляры Stock имеют атрибуты name, shares и price. Например:

>>> import stock
>>> a = stock.Stock('GOOG',100,490.10)
>>> a.name
'GOOG'
>>> a.shares
100
>>> a.price
490.1
>>>

Создайте несколько дополнительных объектов Stock и манипулируйте ими. Например:

>>> b = stock.Stock('AAPL', 50, 122.34)
>>> c = stock.Stock('IBM', 75, 91.75)
>>> b.shares * b.price
6117.0
>>> c.shares * c.price
6881.25
>>> stocks = [a, b, c]
>>> stocks
[<stock.Stock object at 0x37d0b0>, <stock.Stock object at 0x37d110>, <stock.Stock object at 0x37d050>]
>>> for s in stocks:
     print(f'{s.name:>10s} {s.shares:>10d} {s.price:>10.2f}')

... посмотрите на вывод...
>>>

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

Объект, определенный классом, в некоторой степени похож на словарь - просто с другим синтаксисом. Например, вместо записи s['name'] или s['price'] вы теперь пишете s.name и s.price.

✨ Проверить решение и практиковаться

Упражнение 4.2: Добавление некоторых методов

С помощью классов вы можете прикреплять функции к вашим объектам. Они называются методами и являются функциями, которые работают с данными, хранящимися внутри объекта. Добавьте методы cost() и sell() к вашему объекту Stock. Они должны работать так:

>>> import stock
>>> s = stock.Stock('GOOG', 100, 490.10)
>>> s.cost()
49010.0
>>> s.shares
100
>>> s.sell(25)
>>> s.shares
75
>>> s.cost()
36757.5
>>>
✨ Проверить решение и практиковаться

Упражнение 4.3: Создание списка экземпляров

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

>>> import fileparse
>>> with open('portfolio.csv') as lines:
...     portdicts = fileparse.parse_csv(lines, select=['name','shares','price'], types=[str,int,float])
...
>>> portfolio = [ stock.Stock(d['name'], d['shares'], d['price']) for d in portdicts]
>>> portfolio
[<stock.Stock object at 0x10c9e2128>, <stock.Stock object at 0x10c9e2048>, <stock.Stock object at 0x10c9e2080>,
 <stock.Stock object at 0x10c9e25f8>, <stock.Stock object at 0x10c9e2630>, <stock.Stock object at 0x10ca6f748>,
 <stock.Stock object at 0x10ca6f7b8>]
>>> sum([s.cost() for s in portfolio])
44671.15
>>>

Упражнение 4.4: Использование вашего класса

Измените функцию read_portfolio() в программе report.py так, чтобы она читала портфель в список экземпляров Stock, как это показано в упражнении 4.3. После этого исправьте весь код в report.py и pcost.py, чтобы он работал с экземплярами Stock вместо словарей.

Совет: вам не нужно вносить крупные изменения в код. В основном вы будете изменять доступ к словарям, например, s['shares'] на s.shares.

Вы должны быть able to запускать ваши функции так же, как и раньше:

>>> import pcost
>>> pcost.portfolio_cost('portfolio.csv')
44671.15
>>> import report
>>> report.portfolio_report('portfolio.csv', 'prices.csv')
      Name     Shares      Price     Change
---------- ---------- ---------- ----------
        AA        100       9.22     -22.98
       IBM         50     106.28      15.18
       CAT        150      35.46     -47.98
      MSFT        200      20.89     -30.34
        GE         95      13.48     -26.89
      MSFT         50      20.89     -44.21
       IBM        100     106.28      35.84
>>>
✨ Проверить решение и практиковаться

Резюме

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