文章目录
类和对象
1 面向对象的思想
⾯向过程:⾯向处理,更多的是从计算机⻆度思考,注重计算每⼀个步骤,程序更像是⼀本cpu操作⼿册。
⾯向对象:以⽇常⽣活的⻆度思考问题的解决,更接近⼈的思维⽅式,让⼈可以从更⾼的层⾯考虑系统的构建
以你请朋友吃饭为例:
面向过程 | 面向对象 |
---|---|
⾃⼰买菜 | 和朋友⼀块到饭店 |
⾃⼰摘菜 | 叫服务员点菜 |
⾃⼰洗菜 | 和朋友⼀块吃 |
⾃⼰做菜 | |
和朋友⼀块吃 |
⾯向对象的优点:
- ⾯向对象更加适合做应⽤的开发
- ⾯向对象可以使你的代码更加优雅和紧凑
- ⾯向对象开发效率更⾼
- ⾯向对象代码复⽤度更⾼、可维护性更好
⾯向对象是⼀种思维⽅式,它认为万事万物皆对象,程序是由多个对象协作共同完成功能的,所以以后我们要从⾯向过程转向⾯向对象。以⾯向对象的⽅式考虑程序的构建。⾯向对象的核⼼是:类和对象
问题->⾯向对象分析(OOA)->发现对象->类->⽤类实例化对象->对象协作完成功能
2. 类和对象
2.1 类和对象的概念
⽣活⻆度
- 类:具有相同特征和⾏为的对象的集合,是⼀个概念
- 对象:客观存在的⼀切事物,是类的实例
类: 汽⻋ 超级英雄 电脑 杯⼦
对象: 红⾊的宝⻢ 美国队⻓ 桌上的mac pro ⽼王的⿊⾊杯⼦
程序⻆度
- 类:⽤户⾃定义的数据类型,是模板,不占⽤内存
- 对象:由类定义的变量,占⽤内存
类:
成员属性(成员变量) 描述对象的静态特征,诸如,名字、身⾼体重
成员⽅法 描述对象的动态特征,例如:吃饭、睡觉、打⾖⾖
2.2 类的定义
#语法:
class 类名:
类体
注意:
- 类定义必须以关键字class开头
- 类名要符合标识符的规范
- 类名⼀般⽤⼤驼峰⻛格: 每个单词⾸字⺟⼤写,其它⼩写 ,例如MyBook YouMoney
- 类体必须缩进
- 在python3中类默认继承object,所以可以这样写 class Dog:,它等价于class Dog(object):
- ⼀个⽂件⾥只放⼀个类
2.3 成员⽅法
成员⽅法其实就是函数,作⽤域在类内,成员⽅法的第⼀个参数必须是self,self
代表当前对象,也就是调⽤这个⽅法的对象,这个参数由系统传递。
class Dog(object):
def bark(self): #成员⽅法,第⼀个参数必须是self,代表当前调⽤对象
print('我是⼩可爱--丁丁')
dingding = Dog() #实例化⼀个对象
#调⽤⽅法,不需要传参数,self是系统传递的
#调⽤形式: 对象.⽅法([实参])
dingding.bark() #等价调⽤形式:bark(dingding)
注意:
- self参数在调⽤的时候不必传值,由系统传值
- self只能在实例⽅法中使⽤
- ⽅法和函数的区别:
- ⽅法作⽤域属于类,所以即便和普通函数重名,也不会被覆盖
- ⽅法的第⼀个参数必须是self,但函数不要求
- ⽅法必须通过对象调⽤,⽽函数不需要
- ⽅法的第⼀个参数self其实可以使任何合法标识符,不过⼀般约定俗成都是self
- ⽅法的连贯调⽤
class Dog:
def bark(self):
print("汪汪汪")
return self #返回self
def eat(self):
print("爱啃⼤⻣头")
return self
dog = Dog()
dog.eat().bark() #⽅法的连贯调⽤,⽅法要返回self
2.4 对象的创建
对象的创建过程也称之为对象的实例化过程,也就是定义了⼀个类类型的变量或者称之为实例(instance)的过程
#语法: 对象 = 类名([实参])
dingding = Dog() #实例化⼀个对象
print(dingding) #<__main__.Dog object at 0x00000000023F40B8>
print(type(dingding)) #<class '__main__.Dog'>
#查看对象的类名
print(dingding.__class__)
2.5 成员属性
成员属性描述的是对象的静态特征,⽐如说狗名字、品种等,其实就是⼀个变量,作⽤域属于对象,不会和类外的全局变量冲突。python中成员属性可以在构造函数中添加。成员属性属于对象,每个对象的成员属性的值都不同
- 在构造函数中添加的属性属于所有对象(重点)
#添加属性语法:
对象.成员属性 = 值
#引⽤⽅式:对象.成员属性
class Dog(object):
def __init__(self,name,kind,age):
self.name = name
self.kind = kind
self.age = age
def bark(self):
print('我是⼩可爱--丁丁')
dingding = Dog('丁丁','泰迪',3)
print('我是可爱的%s⽝,%s,我今年%d岁了' % (dingding.kind,
dingding.name, dingding.age))
#查看实例属性
print(dingding.__dict__) #__dict__属性可以⽤来查看实例属性
print(dir(dingding)) #查看Dog的属性,包括实例属性
3 构造和析构
3.1 构造⽅法
- ⽬的:构造⽅法⽤于初始化对象(不创建对象),可以在构造⽅法中添加成员属性
- 时机:实例化对象的时候⾃动调⽤
- 参数:第⼀个参数必须是self,其它参数根据需要⾃⼰定义
- 返回值:不返回值,或者说返回None,不应该返回任何其他值
语法:
def __init__(self,arg1,arg2....):
函数体
#参数:arg1,agr2...根据需要⾃⼰定义
#如果⾃⼰不定义构造⽅法,系统⾃动⽣成⼀个构造函数
def __init__(self):
pass
注意:
- 如果没有定义构造⽅法,系统会⽣成⼀个⽆参构造⽅法,如果⾃⼰定义了构造⽅法,则系统不会⾃动⽣成
class 类名:
def __init__(self):
pass
- ⼀个类只能有⼀个构造⽅法,如果定义多个,后⾯的会覆盖前⾯的
- 构造函数由系统在实例化对象时⾃动调⽤,不要⾃⼰调⽤
class Dog(object):
def __init__(self,name,kind,age):
self.name = name #定义对象属性,这个类所有的对象都具有该属性
self.kind = kind #成员属性必须通过self.引⽤,否则是普通变量
self.age = age
def bark(tmp):
print('我是⼩可爱--丁丁')
dingding = Dog('丁丁','泰迪',3)
print('我是可爱的%s⽝,%s,我今年%d岁了' % (dingding.kind,
dingding.name, dingding.age))
3.2 析构⽅法
- ⽬的:对象销毁时,释放资源
- 时机:对象销毁时由系统⾃动调⽤
- 参数:除了self外,没有其他参数
- 返回值:不返回值,或者说返回None。
- 语法:
def __del__(self):
#to do
class Dog(object):
#构造
def __init__(self,name,kind,age):
self.name = name
self.kind = kind
self.age = age
#析构
def __del__(self):
print('拜拜了,⼆⼗年后⼜是⼀条好汉')
def bark(tmp):
print('我是⼩可爱--丁丁')
dingding = Dog('丁丁','泰迪',3)
print('我是可爱的%s⽝,%s,我今年%d岁了' % (dingding.kind,
dingding.name, dingding.age))
del dingding #销毁对象,⾃动调⽤析构⽅法
#在函数中对象,当函数结束运⾏时,⾃动析构
def test():
td = Dog('当当','泰迪',3)
3.3 str
- ⽬的:将对象转化为字符串
- 时机:凡是涉及对象向字符串转换的都会调⽤(print,str)
- 参数:self
- 返回值:字符串
repr 作⽤同__str__ ,不过是给解释器看的
class Animal:
def __init__(self,name,age):
self.name = name
self.__age =age
def __str__(self):
return "name : {} age : {}".format(self.name,self.__age)
def __repr__(self):
return self.__str__()
a1 = Animal('zhu',3)
print(a1)
print('我是⼀头可爱的 ' + str(a1)