1、类
1.1 类的概念
一种数据类型就是类。例如整数,浮点数,字符串。
1.2 类的定义
python 中通过关键字 class
可以定义一个自定义数据类型,基本语法如下:
class 类名: 属性 方法
注意:python 中类名规则同变量,一般使用 大驼峰
来表示。
案例
class Point:
"""
表示平面坐标系中的一个点
"""
print(Point)
<class '__main__.Point'>
2、对象
2.1 对象的概念
某种数据类型的一个具体的数据称为这个类的一个对象或者实例。通过类创建对象叫做实例化。
所谓的面向对象,就是把一些数据抽象成类的思想。
python 是一门面向对象的编程语言,python 中一切皆对象。
函数也是 python 中的一个类,定义的某个函数就是函数类的一个具体实例。
def func():
pass
print(type(func))
<class 'function'>
2.2 实例化
除了基本数据类型实例化的过程中用到的特殊的语法规范外,所有自定义类型进行实例化都是通过调用类名来实现的,非常简单,语法如下:
类名(参数)
案例
给上面创建的 Point
类创建一个实例。
point = Point()
print(type(point))
<class '__main__.Point'>
3、属性
类和对象的特征数据称为属性。
3.1 类属性
类的特征称为类属性。
3.1.1 类属性的定义
直接在类中定义的变量(与 class 语句只有一个缩进),就是类属性。
案例
# 给 Point 类创建一个 name 属性用来表示名称。
class Point:
"""
表示平面坐标系中的一个点
"""
name = '点'
3.1.2 类属性的访问
类属性可以直接通过类名和对象以句点法访问,语法格式如下:
类名.类属性名 对象.类属性名
案例
print(Point.name) # 直接通过类名访问类属性
point = Point() # 创建一个实例
point.name # 通过对象访问类属性
点'点'
注意:如果不存在属性则抛出 AttributeError
的异常
3.2 对象属性
对象的特征数据称为对象属性
3.2.1 对象属性的定义
对象属性一般定义在构造方法中,详见下面构造方法一节。
通过句点法 对象.对象属性
以赋值的方式可以直接定义对象属性。
案例
# 平面坐标系中的每个点都有 x 坐标和 y 坐标,通过类 Point 创建一个对象表示点(x=1,y=2)
point = Point()
# 通过赋值直接定义对象属性
point.x = 1
point.y = 2
注意:在定义对象属性时如果和类属性同名,那么通过对象将无法访问到类属性。
3.2.2 对象属性的访问
通过句点法 对象.对象属性
可以访问对象属性。
案例
# 访问上面案例中的point的x和y的坐标
print(point.x)
print(point.y)
1 2
访问对象属性时,首先会检查对象是否拥有此属性,如果没有则去创建对象的类中查找有没有同名的类属性,如果有则返回,如果都找不到则抛出 AttributeError
的异常
4、方法
定义在类中的函数称为方法。通过调用的方式的不同,分为对象方法
,类方法
,静态方法
和魔术方法
。
4.1 对象方法
定义在类中的普通方法,一般通过对象调用称为对象方法。
4.1.1 对象方法的定义
案例
# 定义函数 my_print,它接收一个 Point 对象,然后打印这个点的 x,y 坐标。
def my_print(point):
print('({},{})'.format(point.x, point.y))
# 实例化一个之前的案例中的Point类
p = Point()
p.x = 1
p.y = 2
my_print(p)
(1,2)
# 定义函数 distance,它接收两个 Point 对象,然后返回这两个点的距离。
def distance(p1, p2):
return ((p1.x-p2.x)**2 + (p1.y-p2.y)**2)**0.5
# 实例化之前的案例中的Point类
p1 = Point()
p2 = Point()
p1.x = 1
p1.y = 2
p2.x = 3
p2.y = 4
res = distance(p1, p2)
print(res)
2.8284271247461903
观察上面的两个函数,发现它们都接收一个或多个 Point 的对象作为参数。为了显式的加强这样的联系,我们可以将它们定义在 Point 的类中。
class Point:
"""
表示平面坐标系中的一个点
"""
name = '点'
def my_print(point):
print('({},{})'.format(point.x, point.y))
def distance(p1, p2):
return ((p1.x-p2.x)**2 + (p1.y-p2.y)**2)**0.5
4.1.2 对象方法的调用
对象方法与属性一样,可以通过句点法进行调用。
类名.方法名(参数) 对象.方法名(参数)
通过类名调用方法时,和普通函数没有区别
# 更新了类,再次实例化对象
point = Point()
point.x = 1
point.y = 2
p1 = Point()
p2 = Point()
p1.x = 1
p1.y = 2
p2.x = 3
p2.y = 4
Point.my_print(point)
res = Point.distance(p1, p2)
print(res)
(1,2) 2.8284271247461903
通过对象调用方法时,对象本身会被隐式的传给方法的第一个参数
point.my_print()
res = p1.distance(p2)
print(res)
(1,2) 2.8284271247461903
因此,定义对象方法会习惯性的把第一个形参定义为 self,表示调用对象本身
class Point:
"""
表示平面坐标系中的一个点
"""
name = '点'
def my_print(self):
print('({},{})'.format(self.x, self.y))
def distance(self, p2):
return ((self.x-p2.x)**2 + (self.y-p2.y)**2)**0.5
point.my_print()
res = p1.distance(p2)
print(res)
(1,2) 2.8284271247461903
4.2 类方法
在类中通过装饰器 classmethod
可以把一个方法变成类方法。
一个类方法把类自己作为第一个实参,就像一个实例方法把实例自己作为第一个实参。
案例
# 定义一个类方法 base_point 用来返回坐标原点
class Point:
"""
表示平面坐标系中的一个点
"""
name = '点'
def my_print(self):
print('({},{})'.format(self.x, self.y))
def distance(self, p2):
return ((self.x-p2.x)**2 + (self.y-p2.y)**2)**0.5
@classmethod # 利用classmathod修饰器,表示是一个类方法
def base_point(cls): # cls表示类本身
bp = cls()
bp.x = 0
bp.y = 0
return bp
通过类本身或者是该类的实例都可以调用类方法。
# 通过实例
p = Point()
bp1 = p.base_point()
bp1.my_print()
# 通过类本身
bp2 = Point.base_point()
bp2.my_print()
(0,0) (0,0)
类方法一般都用来生成特殊对象。
4.3 特殊方法(魔术方法)
在类中可以定义一些特殊的方法用来实现特殊的功能,也称为魔术方法。这些方法一般都以双下划线 __
开头
__init__
__init__
又叫构造方法,初始化方法,在调用类名实例化对象时,构造方法会被调用,类名括号 () 后的参数会传递给构造方法,对象属性一般在这个方法中定义。
案例
上面案例中的 Point 类实例化后,需要手动创建对象属性 x 和 y,这显然容易出错和不规范,正确的做法应该是在构造方法中定义属性 x 和 y
class Point:
"""
表示平面坐标系中的一个点
"""
name = '点'
# __init__方法每次实例化时,都会被调用
def __init__(self, x, y):
self.x = x
self.y = y
def my_print(self):
print('({},{})'.format(self.x, self.y))
def distance(self, p2):
return ((self.x-p2.x)**2 + (self.y-p2.y)**2)**0.5
# 包括类方法,也会直接调用init方法
@classmethod
def base_point(cls):
return cls(0,0)
# 实例化
p1 = Point(1, 2)
p2 = Point(x=3, y=4)
p1.my_print()
p2.my_print()
(1,2) (3,4)
__str__
__str__
方法在对象被 print
函数打印时被调用,print
输出 __str__
方法返回的字符串
案例
上面案例中 Point
类里的 my_print
方法可以去掉,定义一个 __str__
方法
class Point:
"""
表示平面坐标系中的一个点
"""
name = '点'
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return '({},{})'.format(self.x, self.y)
def distance(self, p2):
return ((self.x-p2.x)**2 + (self.y-p2.y)**2)**0.5
@classmethod
def base_point(cls):
return cls(0,0)
p = Point(2,2)
print(p)
(2,2)
4.4 静态方法
在类中通过装饰器 staticmethod
可以把一个方法变静态方法。
静态方法不会接收隐式的第一个参数,它和普通的函数一样,只是被封装到类中。
通过类和对象都可以调用
案例
在 Point 类中定义一个静态方法,用来计算两个数的和。
class Point:
"""
表示平面坐标系中的一个点
"""
name = '点'
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return '({},{})'.format(self.x, self.y)
def distance(self, p2):
return ((self.x-p2.x)**2 + (self.y-p2.y)**2)**0.5
@classmethod
def base_point(cls):
return cls(0,0)
@staticmethod
def sum(x,y):
return x+y
Point.sum(1, 2)
3
p = Point(1, 2) # 实例化
p.sum(3, 4)
7