python核心阶段(二)—— 面向对象在python中的实践
前言(类)
类是将同类对象的共同属性和行为抽象出来形成的一个相对复杂的数据类型
对象的抽象是类,类的具体化就是对象
1. 类的定义及简单应用
- 语法:
class 类名(首字母大写):
xxxx(类的描述)
- 根据类,创建一个对象,这个过程被称为实例化,所以有时对象也被称为实例
语法: xxx = 类名()
- 对象通过class属性可以找到对应的类
语法:对象.__class__
class Money: # 注1.首字母大写 2.Money后面不加括号
pass #占位符
one = Money() #根据类创建一个对象
print(one.__class__) #对象通过class属性可以找到类
2.属性相关
2.1 属性与变量的区别
1)概念 :变量是“可以改变的量值” ; 属性是“属于某个对象的特性”
2)访问权限:对于变量,根据不同的位置,存在不同的访问权限(例如局部变量和全局变量)
对于属性,只能通过对象来进行访问,所以必须先找到对象,而对象又通过变量
名来引用,所以它也有对应的访问权限
3)判定依据:是否存在宿主(属性的宿主是对象)
2.2 对象属性
- 在对象中操作的属性
语法 | 操作 | 备注 |
---|---|---|
对象.属性 = 属性的值 | 增加/修改对象属性 | 对于可变类型的数据,例如列表,若直接修改,需要开辟一个新的内存空间;利用l.append函数,则不需要 |
对象.__dict__ | 查询对象的所有属性 | 本质:__dict__ 也是一个属性,专门用于 存储所有属性 |
对象.属性 | 访问对象 | 如果访问不到,会报错 |
del 对象.属性 | 删除对象属性 |
class Person: #创建类
pass
p = Person() #创建对象
p.age = ["a","b"] #新增属性
p.age.append("c") #在原内存修改
p.age = ["a","b","c"] #开辟新内存
print(p.age) #访问属性
print(p.__dict__) #查询所有属性
del p.age #删除属性
2.3 类属性
- 在类中操作的属性,类属性被各个对象所共享
- 万物皆对象,类也是一个对象,一般称作类对象,所以类属性操作与对象属性类似
语法 | 操作 | 备注 | ||
---|---|---|---|---|
类名.类属性 = 值 | 增加/修改类属性 | 一般直接在类定义是增加属性,例如 class Animal: age = 1 | ||
类名.类属性 | 访问类属性 | 通过类访问 | python属性查找机制:优先到对象自身查询,然后根据__class__到对应的类去查询 | |
对象.类属性 | 通过类的对象访问 | |||
del 类名.属性 | 删除类属性 |
- 注:只能通过类名增/改/删,不能通过对象增/改/删,通过对象只能进行访问
- 类属性的存储问题
一般情况下,属性存储在 名为__dict__属性 的字典当中,对象属性能直接通过__dict__属性 修改,但类属性不型
2.4 类属性和对象属性区别及补充
- 区别:
- 存储地点不同:类属性存储在类中,对象属性存储在对象中
- 抽象层次不同:类是根据同类对象的相同属性和行为抽象出来的,抽象层次更高
- 宿主不同:对象属性的宿主是对象,类属性宿主是类对象
- 补充:通过类限制对象属性的添加
在定义类时,设置类属性:__slots__ = [ ]
只有列表中的属性,才可以被这个类创建的对象添加
class Animal:
__slots__ = ["age","height"] #只有 age 和 heigh 才可以被添加
pass
a = Animal() #创建对象
a.height = 1 #可以添加
a.weight = 2 #不能添加
3.方法(行为)相关
3.1 方法的概念
描述一个目标的行为动作,和函数非常相似,都封装了一系列的行为动作,被调用之后执行
他和函数的主要区别是调用方式不同
- 方法的调用语法: 目标.方法名() 其中目标为对象、类...... 取决于方法的类型
def eat():
print("stay with you")
eat() #调用函数
class Person:
def eat2(self): # 定义一个方法
print("too bad")
p = Person() #创建一个对象 实例化
Person.eat2() #调用方法
3.2 方法的划分
- 划分依据:方法的第一个参数 必须要接受的数据类型
- 存储位置:不管哪种方法,都是存储在类当中,即类的__dict__字典中,没有存储在实例中的
方法类型 | 判断依据 | 语法 | 调用 |
---|---|---|---|
实例方法 | 默认第一个参数需要接收到一个实例 | class 类名: def 方法名(self,xxx): xxxx | 实例.方法名() 通过实例调用方法时,实例会默认作为第一个参数,所以括号里只需要填第二个及以后的参数即可 |
类方法 | 默认第一个参数需要接收到一个类 | class 类名: @classmethod def 方法名(cls,xxx): xxxx | 类 / 实例.方法名() 同上,但它也可以通过实例来调用,只不过实例会被忽略,会传递实例对应的类给第一个参数 |
静态方法 | 第一个参数什么都不默认接收 | class 类名: @staticmethod def 方法名(): xxxx | 类 / 实例.方法名() 直接调用,通过类或者实例调用都可以,两者都会被忽略,只起调用作用 |
# 代码演示
class Person: #定义一个类
def shilifangfa(self,people): # 定义实例方法,第一个参数需接受一个实例
print("《孤独娱乐》",people)
@classmethod # 定义类方法,第一个参数需接受一个类
def leifangfa(cls,man):
print("《稻香》",man)
@staticmethod # 定义静态方法
def jingtaifangfa(woman):
print("《泡沫》",woman)
p = Person() #通过类创建一个实例
p.shilifangfa("林俊杰") # 通过实例,调用实例方法
Person.leifangfa("周杰伦") # 通过类或实例,调用类方法
p.jingtaifangfa("邓紫棋") # 通过类或实例,调用静态方法