接下来进入第五章的学习:面向对象基础
一、类
1.类(class):由3部分组成
类的名称:类名
类的属性:一组数据
类的方法:允许对其操作的方法(行为)
例如
#设计一个人类
类名: People
属性: 身高 体重 年龄 性别
行为(方法):吃饭 睡觉
2.那么我们该如何去定义类呢?
class 类名:
属性列表
方法列表
例如:定义一个猫类
class cat(object): #继承object父类
legs = 4 #这就是猫的属性
#像猫的其他属性如颜色什么的,每只猫都不一样,我们要后面用init去输入每只猫的颜色,这里放后面去讲
def eat(self): #这些就是猫的行为(方法)
print('猫吃老鼠')
def drink(self):
print('猫喝水')
cat1=cat() #这样cat1就有了cat的所有属性
print(cat1.legs) #是4
cat1.eat() #输出'猫吃老鼠'
3.类添加属性
在我们定义完一个类之后,创建了类的对象,我们可以手动给这个对象添加属性
定义一个人类
class Person(object):
#属性:身高,体重,年龄
#行为:吃饭 睡觉 喝水
#定义一个普通方法
def eat(self):
print('人都要吃饭')
#定义一个普通方法
def sleep(self):
print('人都要休息')
P=Person()
P.name = '张三' #这样就给他添加上属性了
4.init()方法 (初始化方法)
class 类名:初始化方法,用来完成一些默认的设置
def __init__(self):
函数体语句 #类去赋值对象的时候会直接运行这个函数
例如定义一个汽车类
class cars(object):
def __init__(self,color,wheelnum):
self.color = color
self.wheelnum = wheelnum
def move(self):
print('车子在移动...')
def whistle(self):
print('汽车在鸣笛')
car1=cars('white','4') #就需要在赋类的时候输出参数
print(car1.color)
car1.move()
创建完之后依然可以修改其属性的值
car1.color='black' #直接这样修改就好了
5.del()方法 (析构方法)
创建对象后,python解释器默认调用__init__()
同样,当删除一个对象的时候,python解释器也会默认调用__del__()
class Animal(object):
#定义初始化方法 创建对象时候自动调用
def __init__(self,name):
self.name = name
#定义普通方法
def walk(self):
print('动物会跑')
#定义一个析构方法 删除对象的时候自动调用
def __del__(self):
print('%s对象被干掉'%(self.name))
dog = Animal('哈皮狗')
dog.walk()
del dog #这时候会输出 哈皮狗对象被干掉
print(dog.walk()) #就会报错了
但是呢,要在对象的引用计数为0时,对象才是真正的被删除
#创建一个cat对象
cat = Animal('波斯猫')
cat2 = cat
cat3 = cat
print('删除对象1')
del cat
print('删除对象2')
del cat2
print('删除对象3')
del cat3
# 只有在cat3被删除后,才会输出 波斯猫对象被干掉
python 会在程序结束前自动调用del
总结:
变量保存了对象的引用,对象的引用计数加1,
使用__del__()删除对象的时候,对象的引用计数-1,对象被删除
如果对象的引用计数不是1,每删除一次对象的引用计数减1,直到引用计数为0时候
该对象才被真正的删除
6.魔方方法
魔方方法:
特殊方法:是指被包含下划线的方法或者所能调用到的方法的统称,这些通常会在特殊的情况下调用,并且基本没有手动调用他们的必要。
例如__str__ 定义一个车类
class Car(object):
#定义初始化方法 创建对象的时候被自动调用
def __init__(self,newColor,newWheelNum):
self.color = newColor
self.wheelNum = newWheelNum
#定义一个析构方法 删除对象的时候被自动调用
def __del__(self):
print('%s对象被删除'%(self.color))
#定义一个魔方方法
def __str__(self):
msg = '%s-%d'%(self.color,self.wheelNum)
return msg
#创建一个对象laosi
laosi = Car('红色',4)
print(laosi)
总结:如果类的属性比较多,可以重写__str__()方法打印属性,方便阅读,无需手动调用,当使用print打印对象的时候,自动调用
7.重写一般方法和重写特殊的构造方法
重写涉及一个概念:继承
如果现在有两个类A(父类),B(子类) 如果子类B继承父A, ,类B的某个方法被调用的时候先从B中找,如果找不到再去A中找,如果在A找不到----》基类 (object)
class 命名(基类==父类):
#声明一个父类A
class A(object):
#声明一个普通方法
def sayHello(self):
print('我是A')
#声明一个子类B
class B(A): #B类后面圆括号里面继承的父类名字
#声明一个普通方法
# def sayHello(self):
# print('我是B')
8.理解一下self
class Animal(object):
#定义一个初始化方法
def __init__(self,name):
self.name = name
#定义一个普通方法
def printName(self):
print('动物的名字是:%s'%self.name) #self=dog
dog=Animal('哈士奇')
dog.printName() #动物的名字是:哈士奇
总结:self可以理解成对象的本身
我们来做一个烤地瓜的应用熟悉一下类的使用
类名:SweetPotato
属性:根据数字判断地瓜的生熟度 0~3生的 3~5半生不熟 5~8烤熟了 8以上烤糊了,有番茄酱 芥末 蜂蜜
class sweetpotato(object):
def __init__(self):
self.cooklevel = 0
self.cookstring = '生的'
self.condiments=[]
def cook(self,time):
self.cooklevel += time
if 0<self.cooklevel<=3:
self.cookstring='生的'
elif 3<self.cooklevel <=5:
self.cookstring='半生不熟'
elif 5 <self.cooklevel<=8:
self.cookstring='烤熟啦'
elif self.cooklevel >8:
self.cookstring='烤糊了哈哈'
def addcondiments(self,condiment):
self.condiments.append(condiment)
def __str__(self):
str1='%s,%s'%(self.cookstring,self.condiments)
return str1 #有这个就不用我一个个输出它的属性了
s = sweetpotato()
print('开始测试烤地瓜')
s.cook(4)
print(s)
s.cook(4)
print(s)
s.addcondiments('芥末')
s.addcondiments('蜂蜜')
print(s)
蛮有意思的 可以看看哈哈哈
9.访问限制
如果有一个对象,当需要对其进行修改属性:
1.直接修改 对象名.属性名 = 新数据
2.间接修改 对象名.方法名()
将属性定义为私有:__双下划线后面跟属性名
直接看例子把会更让人懂一些
#定义一个人类
class Person(object):
#定义一个初始化方法
def __init__(self,name,money):
self.__name = name
self._money = money
#定义普通方法对属性设置
def setName(self,value):
#数据过滤
if len(value) <= 4:
self.__name = value
else:
print('名称的长度不能大于4个字符')
#定义普通方法获取属性值
def getName(self):
return self.__name
#定义私有方法
def __sayHello(self):
print('我的名字是:%s,我有%s存款'%(self.__name,self._money))
#定义公有方法获取私有属性
def test(self):
self.__sayHello()
然后这时候我们创建一个对象p
p = Person('张三','99999999')
print(p.name) #是不让访问的哦
Print(p.__name) #也同样不行
那应该怎么办呢?我们可以通过方法去访问他
print(p.gerNmae())
那么不能通过对象访问,自然也不能通过对象修改值了
同样啊,私有方法不能直接访问的
那么什么又是半公开属性呢,就是他是受保护的属性,Python中有个默认的规定,即在属性名前加上单个下划线(_属性名)来表示这是个受保护的属性,虽然Python解释器不会对使用单个下划线前缀的属性名做特殊处理,但程序员们会严格遵守这个约定,不会在类外部访问这种属性
私有属性为什么不能在类外访问?
因为_name python解释器将它转换成_Person__name,可以通过_Person__name访问,但是不建议这样做
p._Person__name = '李淑芬'
print(p.getName())
二、继承
继承的概念:在现实生活中,一般指子女继承父辈的基因,财产
1.单继承
一个子类继承父类的方法,但不会继承属性
class Cat(object):
#定义初始化方法
def __init__(self,name,color):
self.name = name
self.color = color
#定义一个普通方法
def eat(self):
print('猫喜欢吃老鼠')
#定义子类Bosi继承父类Cat
class Bosi(Cat):
#定义初始化方法
def __init__(self,type,num):
self.type = type
def sleep(self):
print('睡觉呢')
bosi=Bosi('bosi',4)
bosi.eat() #'猫喜欢吃老鼠'
2.多继承
简而言之就是继承多个父类
class A(object):
def test(self):
print('test----A')
#声明一个父类B
class B(object):
def test(self):
print('test---B')
#声明一个子类,同时继承A和B两个父类
class C(A,B):
def test(self): #理解方法重写:比如语言 父母一般只会汉语 我们还会其他语言 比如英语 日语
print('test----C')
#创建一个对象c
c = C()
c.test() #是输出test----c,但如果没有这个,就是输出test-----A
print(C.__mro__)#可以打印查看执行方法的顺序
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
总结:一个子类同时继承了多个父类,如果调用同名的方法,先从子类找,子类没有到父类里面找根据就近原则
3.重写父类
重写父类其实就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖父类中的方法,跟刚刚讲的那个就近原则一样
class Person(object):
#定义普通方法
def lunch(self):
print('人都需要吃饭')
#定义一个子类Student,继承父类Person
class Student(Person):
#子类重写和父类同名的方法
def lunch(self):
print('学生需要吃饭')
#创建Student对象s
s = Student()
s.lunch() #'学生需要吃饭'
那么子类要怎么样才能继承父类的属性呢
emm准确意义上来说不是继承父类的属性,是可以直接调用父类的__init__函数
class Person(object):
#定义初始化方法
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
#定义普通方法
def eat(self):
print('人都需要吃饭')
#定义普通方法
def speak(self):
print('我会汉语')
#定义子类Student继承父类Person
class Student(Person):
#定义初始化方法
def __init__(self,name,age,sex,no): #有三种方法的
# 调用父类同名方法
#1.父类类名.父类初始化方法
# Person.__init__(self,name,age,sex)
# 2.super()
# super().__init__(name, age, sex)
#3.super()
super(Student,self).__init__(name, age, sex)
self.no = no
#创建一个对象
s = Student('张学友',20,'男',110)