将一些基本数据类型复合成一个自定义类型。
向类外提供必要的功能,隐藏实现的细节。简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。
可以声明私有成员。
私有成员的名称被修改为:_类名__成员名
,可以通过 __dict__
属性查看。
class MyClass:
def __init__(self, data):
self.__data = data
def __func01(self):
print("func01执行了")
m01 = MyClass(10)
# print(m01.__data) # 无法访问
print(m01._MyClass__data)
print(m01.__dict__) # {'_MyClass__data': 10}
# m01.__func01() # 无法访问
m01._MyClass__func01()
属性@property:
属性可以保护实例变量,限制变量在有效范围内。
@property
def 属性名(self):
return self.__属性名
@属性名.setter
def 属性名(self, value):
self.__属性名= value
# 调用
对象.属性名 = 数据
变量 = 对象.属性名
属性的三种形式
# 1. 读取属性:限制变量在有效范围内。
class MyClass:
def __init__(self,data):
self.data = data #
@property
def data(self):
return self.__data
@data.setter
def data(self, value):
self.__data = value
m01 = MyClass(10)
print(m01.data)
# 2. 只读属性:为私有变量提供读取功能。
class MyClass:
def __init__(self):
self.__data = 10
@property
def data(self):
return self.__data
m01 = MyClass()
# m01.data = 20# AttributeError: can't set attribute
print(m01.data)
# 3. 只写属性:比较特殊,需要展开写 property 函数。而且确实很难用得上。
class MyClass:
def __init__(self, data):
self.data = data
# 第一种方法
# data = property()
# @data.setter
# def data(self, value):
# self.__data = value
# 第二种方法
def data(self, value):
self.__data = value
data = property(fset=data) # 这里不放读的函数,就叫只写
m01 = MyClass(10)
print(m01.data) # AttributeError: unreadable attribute
m01.data = 20
子类直接拥有父类的方法。也就是说子类放个性,父类放的是子类的个性。
class 父类:
def 父类方法(self):
方法体
class 子类(父类):
def 子类方法(self):
方法体
儿子 = 子类()
儿子.子类方法()
儿子.父类方法()
是一种
的判定和是
的判定,包含成分都算是一种
,两个完全相同算作是
。前者使用下面的内置函数,后者使用 ==
isinstance(对象, 类型)
:返回指定对象是否是某个类的对象。
issubclass(类型,类型)
:返回指定类型是否属于某个类型。
子类如果没有构造函数,将自动执行父类的,但如果有构造函数将覆盖父类的。此时必须通过super()
函数调用父类的构造函数,以确保父类实例变量被正常创建。
class 子类(父类):
def __init__(self,父类参数,子类参数):
super().__init__(参数) # 调用父类构造函数
self.实例变量 = 参数
类名.mro()
返回类解析的顺序。__str__
函数:将对象转换为字符串(对人友好的)算数运算符
class Vector2:
"""
二维向量
"""
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return "x是:%d,y是:%d" % (self.x, self.y)
def __add__(self, other):
return Vector2(self.x + other.x, self.y + other.y)
v01 = Vector2(1, 2)
v02 = Vector2(2, 3)
print(v01 + v02) # v01.__add__(v02)
复合运算符重载
没有重载 __iadd__
的时候默认使用 __add__
。这里iadd是+=,add是+,两者的区别是+=是在修改,而+是在创建。
class Vector2:
"""
二维向量
"""
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return "x是:%d,y是:%d" % (self.x, self.y)
# + 创建新
def __add__(self, other):
return Vector2(self.x + other.x, self.y + other.y)
# += 在原有基础上修改(自定义类属于可变对象)
def __iadd__(self, other):
self.x += other.x
self.y += other.y
return self
v01 = Vector2(1, 2)
v02 = Vector2(2, 3)
print(id(v01))
v01 += v02
print(id(v01))
print(v01)
比较运算重载
class Vector2:
"""
二维向量
"""
def __init__(self, x, y):
self.x = x
self.y = y
# 决定相同的依据
def __eq__(self, other):
return self.x == other.x and self.y == other.y
# 决定大小的依据
def __lt__(self, other):
return self.x < other.x
v01 = Vector2(1, 1)
v02 = Vector2(1, 1)
print(v01 == v02) # True 比较两个对象内容(__eq__决定)
print(v01 is v02) # False 比较两个对象地址
list01 = [
Vector2(2, 2),
Vector2(5, 5),
Vector2(3, 3),
Vector2(1, 1),
Vector2(1, 1),
Vector2(4, 4),
]
# 必须重写 eq
print(Vector2(5, 5) in list01)
print(list01.count(Vector2(1, 1)))
# 必须重写 lt
list01.sort()
print(list01)