Введение
В этом разделе介绍了类声明和创建新对象的概念。
This tutorial is from open-source community. Access the source code
💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал
В этом разделе介绍了类声明和创建新对象的概念。
Техника программирования, при которой код организован в виде коллекции объектов.
Объект состоит из:
Вы уже использовали некоторое ОО в рамках этого курса.
Например, манипуляция списком.
>>> 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
. Можно скопировать его.
В разделах 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
.
С помощью классов вы можете прикреплять функции к вашим объектам. Они называются методами и являются функциями, которые работают с данными, хранящимися внутри объекта. Добавьте методы 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
>>>
Попробуйте выполнить следующие шаги, чтобы создать список экземпляров 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
>>>
Измените функцию 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, чтобы улучшить свои навыки.