# 班级¶

class Rectangle:
"""A rectangle that is described by its length and width."""

def __init__(self, length, width):
self.length = length
self.width = width

def area(self):
"""Return the area of the rectangle."""
return self.length*self.width

def perimeter(self):
"""Return the perimeter of the rectangle."""
return 2*(self.length + self.width)


def __init__(self, length, width):
self.length = length
self.width = width


As you use classes you instantiate objects of that class. During the instantiation you can provide some initial arguments to the class to customize the resulting object using the special __init__ method. In this example a rectangle object can be initialized with values for its length $$l$$ and for its width $$w$$. These values are then stored in the instance as attributes. The reference to the instance is the self argument, that each method has as its first argument. So by attaching information to self, each distinct object has its own state.

$a=l\cot b$

def area(self):
"""Return the area of the rectangle."""
return self.length*self.width


$P=2(l+b)$

def perimeter(self):
"""Return the perimeter of the rectangle."""
return 2*(self.length + self.width)


first_rectangle = Rectangle(length=2, width=3)
print('Length:', first_rectangle.length)
print('Width:', first_rectangle.width)
print('Area:', first_rectangle.area())
print('Perimeter:', first_rectangle.perimeter())


Information about the first rectangle
Length: 2
Width: 3
Area: 6
Perimeter: 10


second_rectangle = Rectangle(length=5, width=7)
print('Length:', second_rectangle.length)
print('Width:', second_rectangle.width)
print('Area:', second_rectangle.area())
print('Perimeter:', second_rectangle.perimeter())


Information about the second rectangle
Length: 5
Width: 7
Area: 35
Perimeter: 24


## 继承¶

square = Rectangle(length=2, width=2)


class Square(Rectangle):
"""A square that is described by its side length."""

def __init__(self, side_length):
super().__init__(length=side_length, width=side_length)


Rectangle 类的名称初始化 Square 类后面的括号包含 Rectangle 。这告诉Python， Rectangle 类是 超类Square ，即， Square 继承自 Rectangle 。继承意味着，如果没有另外定义， Square 具有与其超类完全相同的方法定义 Rectangle

def __init__(self, side_length):
self.side_length = side_length


def __init__(self, side_length):
self.length = side_length
self.width = side_length


def __init__(self, side_length):
super().__init__(length=side_length, width=side_length)


first_square = Square(side_length=2)
print('Length:', first_square.length)
print('Width:', first_square.width)
print('Area:', first_square.area())
print('Perimeter:', first_square.perimeter())


Information about the first square
Length: 2
Width: 2
Area: 4
Perimeter: 8


## 类型检查¶

def what_is_it(object):
if isinstance(object, Rectangle):
print('It is a rectangle.')
if isinstance(object, Square):
print('It is a square.')


what_is_it(first_rectangle)


It is a rectangle.


what_is_it(first_square)


It is a rectangle.
It is a square.


## 特殊方法¶

Python类的某些行为是按照所谓的 Special method names 。有关如何使用它们的示例，请参见以下内容：

import math

class FreeVector:
"""A vector that is not bound by an initial or terminal point."""

def __init__(self, vector):
self.vector = tuple(vector)

@property
def magnitude(self):
return math.sqrt(math.fsum(v**2 for v in self.vector))

@property
def direction(self):
magnitude = self.magnitude
return tuple(v/magnitude for v in self.vector)

def __repr__(self):
return '{self.__class__.__name__}(vector={self.vector!r})'.format(
self=self)

def __str__(self):
return str(self.vector)

def __eq__(self, other):
if (isinstance(other, FreeVector) and
all(math.isclose(a, b) for a, b in zip(
other.vector, self.vector))):
return True
else:
return False

def __neq__(self, other):
return not self.__eq__(self, other)

if not isinstance(other, FreeVector):
return NotImplemented
return tuple(a + b for a, b in zip(self.vector, other.vector))

def __sub__(self, other):
if not isinstance(other, FreeVector):
return NotImplemented
return tuple(a - b for a, b in zip(self.vector, other.vector))


>>> a = FreeVector((1, 2, 3))
>>> a
FreeVector(vector=(1, 2, 3))
>>> str(a)
'(1, 2, 3)'
>>> b = FreeVector((1, 2, 3))
>>> c = FreeVector((4, 5, 6))
>>> a == b
True
>>> a == c
False
>>> a + c
(5, 7, 9)
>>> c - a
(3, 3, 3)


## 练习¶

• 复制 Rectangle 类，并通过添加一个方法来扩展它 aspect_ratio 它返回其长度与宽度的比率。

• 定义 Circle 使用半径初始化 $$r$$ 作为定义属性。实施 areaperimeter 相应的类。

• 阅读并阅读“面向对象设计中的技能构建”一书，以了解面向对象设计的过程。