面向对象的概念
-
对于面向过程的思想: 需要实现一个功能的时候,看重的是开发的步骤和过程,每一个步骤都需要自己亲力亲为,需要自己编写代码(自己来做)
-
对于面向对象的思想:当需要实现一个功能的时候,看重的并不是过程和步骤,而是关心谁帮我做这件事(偷懒,找人帮我做)
-
面向对象的三大特征有:封装性、继承性、多态性。
1.洗衣服 面向过程(手洗):脱衣服、找一个盆、加水、加洗衣粉、浸泡30分钟、搓洗、拧衣服、倒掉水、再加水、漂洗、拧衣服、倒掉水、晾衣服。 面向对象(机洗):脱衣服、放入洗衣机、按下开关、拿出衣服晾晒。 2.买电脑 面向过程(自己买):需要电脑、查询参数信息、横向比较机型、了解打折信息、与店家讨价还价、下单、收快递、开机验货、确认收货。 面向对象(找人买):需要电脑、找秘书帮我买、收电脑。
类和对象
-
对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类
-
面向对象的语言当中,“类”就是用来模拟现实事物的。
-
类是具有相似内部状态和运动规律的实体的集合(或统称为抽象)。具有相同属性和行为事物的统称
-
类中也有属性、行为两个组成部分,“对象”是类的具体实例
-
属性:事物的特征描述信息,用于描述某个特征“是什么”。
-
行为:事物的能力行动方案,用于说明事物“能做什么”。
把类看成模型图纸,实例对象是按照图纸制造的实物
类的构成
类的命名:如,人类,鱼类,鸟类…
类的属性:如,人的身高、体重、年龄、性别等属性
类的行为:如,人的跑、跳、唱、叫等动作
人类的设计
1.类名:person
2.属性:姓名,性别,年龄,身高
3.行为:唱,跳,跑
类的定义
定义一个类,语法格式
class 类名():
方法列表(被定义的各种方法)
class Person():
def info(self): #类里定义的方法都有一个默认self参数
print('调用实例方法info')
#实例化一个人类对象cxk
cxk = Person()
#调用实例方法
cxk.info()
①类的命名规则和变量的命名规则一样,推荐使用"驼峰命名法"
②info 是一个实例方法,第一个参数一般默认的是self,表示实例对象本身,self也可以换成其他名字,其作用是一个变量,作用是指向实例对象本身
实列属性
一个人的属性有身高、体重、年龄、性别等,要定义具体的一个人,就需要定义这个人的身高、体重等属性。
class Person():
def jineng(self):
print("主角使用技能")
# 实例化一个人类对象李逍遥
lxy = Person()
#给对象添加实例属性和属性值
lxy.name="李逍遥"
lxy.height=178
lxy.age=18
lxy.jinen="爱无限"
#获取实例属性
print('仙剑一主角:',lxy.name)
print('主角的年龄:',lxy.age)
print('主角的身高:',lxy.height)
print('主角的终极技能:',lxy.jinen)
lxy.jineng() #调用实例方法
#运行结果
#仙剑一主角: 李逍遥
#主角的年龄: 18
#主角的身高: 178
#主角的终极技能: 爱无限
#主角使用技能
实例方法
在类中被定义能够被实例化对象调用的方法。
class Person():
def chi(self):
print("吃的方法")
def he(self):
print("喝的方法")
def wan(self):
print("玩的方法")
#实例化一个对象小明
xiaoming = Person()
#调用实例方法
xiaoming.chi()
xiaoming.he()
xiaoming.wan()
#运行结果
#吃的方法
#喝的方法
#玩的方法
魔法方法__init__()
在创建实例对象后再添加实例属性就显得不太合适,能不能在定义类的时候就定义好属性,实例化对象后直接使用定义好的属性。这就是魔法方法__init__()的作用
1.Python 的类里提供的,两个下划线开始,两个下划线结束的方法就是魔法方法
2.__init__()就是一个魔法方法,通常用来做属性初始化 或 赋值 操作。
3.如果类面没有写__init__方法,Python会自动创建,但是不执行任何操作,
4.如果为了能够在完成自己想要的功能,可以自己定义__init__方法,
5.所以一个类里无论自己是否编写__init__方法 一定有__init__方法。
class ZJ():
def __init__(self):
self.name = '李逍遥' #实列属性
self.sex = '男'
self.age = 18
self.height = 178
lxy=ZJ()
print('仙剑一主角:',lxy.name)
print('主角的年龄:',lxy.age)
print('主角的身高:',lxy.height)
#运行结果
#仙剑一主角: 李逍遥
#主角的年龄: 18
#主角的身高: 178
有参数的__init__()的使用方法
class Person():
def __init__(self, name, sex, age, height):
self.name = name #实列属性
self.sex = sex
self.age = age
self.height = height
lxy=Person('李逍遥','男',18,178)
print('仙剑一主角:',lxy.name)
print('主角的年龄:',lxy.age)
print('主角的身高:',lxy.height)
#运行结果
#仙剑一主角: 李逍遥
#主角的年龄: 18
#主角的身高: 178
注意:
①在类内部获取 属性 和 实例方法,通过self获取;
②在类外部获取 属性 和 实例方法,通过对象名获取。
③如果一个类有多个对象,每个对象的属性是各自保存的,都有各自独立的地址;
④但是实例方法是所有对象共享的,只占用一份内存空间。类会通过self来判断是哪个对象调用了实例方法。
模法方法__str__()
使用print输出一个对象的时候只能打印出一串内存地址,如果定义了__str__(self)方法,使用print输出对象时就会自动执行__str__(self)方法,打印出return的数据。
class Person():
def __init__(self, name, sex, age, height):
self.name = name
self.sex = sex
self.age = age
self.height = height
def rap(self):
print('%s 唱了一首歌' %self.name)
def jump(self):
print('%s 跳了起来' %self.name)
def run(self):
print('%s 跑了起来' %self.name)
def __str__(self):
return '姓名:%s 性别:%s 年龄:%s 身高:%s'%(self.name,self.sex,self.age,self.height)
cxk = Person('菜虚鲲','男',18,180)
print(cxk)
cxk.rap()
cxk.jump()
cxk.run()
#运行结果
#姓名:菜虚鲲 性别:男 年龄:18 身高:180
#菜虚鲲 唱了一首歌
#菜虚鲲 跳了起来
#菜虚鲲 跑了起来
公有和私有
公有的方法和属性可以被所有实例化对象调用,而私有的方法和属性只能在类的内部被调用。对象的某些方法和属性只希望在函数内部使用而不希望被外部访问,想要私有化方法只需要在定义函数的时候在函数名前使用两个下划线 __ 即可
1.私有方法
class a():
def foo(self): #该方法公有
pass
def __foo(self): #该方法私有,外部调用会报错
pass
b=a()
b.__foo()
#运行结果
# AttributeError: 'a' object has no attribute '__foo'
2.私用属性
- 对象外部无法访问私有属性
- 对象内部可以访问私有属性(在该类的内部都可以使用)
class a():
def __init__(self):
self.name="小明"
self.__age=18
def b(self):
print(f"{self.name}的年龄是{self.__age}")
xiaoming=a()
print(xiaoming.name)
print(xiaoming.__age)
xiaoming.b()
#运行结果
# 小明
# AttributeError: 'a' object has no attribute '__age'
# 小明的年龄是18
3.伪私有属性和私有方法
python并没有真正意义上的私有
实际上,是在给属性、方法命名时,对名称做了一些特殊处理,使得外界无法访问到。
访问私有
处理方式:在名称前面加上 【_类名】→【_类名__属性/方法名称】
class a():
def __init__(self):
self.name="小明"
self.__age=18
def b(self):
print(f"{self.name}的年龄是{self.__age}")
def __c(self):
print("私有方法被访问")
xiaoming=a()
print(xiaoming._a__age)
xiaoming._a__c()
#运行结果
#18
#私有方法被访问
类的继承
如果一个类里的方法和属性和另一个需要定义的类里的功能相同,那还需要在重新定义么?能不能直接调用已经完成的类里的方法和属性呢?这就是类的继承
class Father(object): #创建一个父类,object表示是该类是python中最顶级的父类
def __init__(self):
self.name = "父亲"
self.age = 40
self.sex = "男"
def BaJiQuan(self):
print("八极拳法")
class son(Father): #创建一个子类,没有任何属性和方法
pass
ez = son() #实例化一个对象儿子
print(ez.name) #通过子类使用父类的属性
ez.BaJiQuan() #通过子类调用继承父类的方法
#运行结果
#父亲
#八极拳法
从结果可以知道,子类可以调用父类的属性和方法,那儿子能不能有自己的属性和方法呢?当然可以。
class Father(): #父类
def __init__(self):
self.name = "父亲"
self.age = 40
self.sex = "男"
self.height=180
def BaJiQuan(self):
print("八极拳")
class son(Father): #子类
def __init__(self):
self.name = "儿子"
self.age = 18
self.sex = "男"
def yongchun(self):
print("咏春拳法")
def BaJiQuan(self):
print("新八极拳法")
ez = son()
print(ez.name) #儿子
print(ez.height)#报错,AttributeError: 'son' object has no attribute 'height'
ez.BaJiQuan() #新八极拳法
ez.yongchun() #咏春拳法
由此可见,当子类定义一个和父类相同的属性名或方法名时,父类的属性和方法就会被子类的覆盖,调用的时候就不会调用父类的方法和属性
现在我们知道子类可以继承父类的方法和属性,那能不能继承多个父类呢?
类的多继承
一个人可以有多个老师,一个类也可以有多个父类
class A():
def __init__(self):
self.name = "老师A"
self.age = 40
self.sex = "男"
self.height=180
def BaJiQuan(self):
print("八极拳法")
def info(self):
print("师傅A的方法")
class B():
def __init__(self):
self.name = "老师B"
self.age = 25
self.sex = "女"
self.height = 170
def yongchun(self):
print("咏春拳法")
def info(self):
print("师傅B的方法")
class c(A,B):
pass
ez = c()
print(ez.name) #调用重名父类的属性
print(ez.sex)
ez.info() #调用重名的父类方法
ez.BaJiQuan()
ez.yongchun()
#运行结果
#老师A
#男
#师傅A的方法
#八极拳法
#咏春拳法
可以知道,一个子类是可以同时继承多个父类的方法的。但是但父类中有重名的方法和属性时,优先使用的是第一个父类中的方法和属性是第一个父类不是指定义的顺序而是子类里继承的顺序。左边的优先级高于右边