Python——创建类和对象
Posted wf-aiyouwei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python——创建类和对象相关的知识,希望对你有一定的参考价值。
####创建类和对象###
1.类的相关知识
类有两种作用:属性应用和示例化
(1)属性的引用(类名.属性)
定义一个类 --> 里面定义一个属性(但是这个属性是写死在程序里的) --> 每一个引用这个属性的都是一样的内容
(2)实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特有的属性
关于类里的方法括号中的self:
self 在实例化时自动将对象/实例本身传给__init__的第一个参数
self 也可以说是:哪一个对象调用这个方法,self就是哪一个对象的引用
在类封装的方法内部,self就表示当前调用方法的对象自己
--调用方法时,程序员不需要传递self参数(但是定义的时候,第一个参数必须是self)
--在方法内部:可以通过self.访问对象的属性
--在方法内部:可以通过self.调用其他的对象方法
示例:
class Cat:
"""这是class Cat的信息"""
def eat(self):
print ‘%s爱吃鱼‘ %self.name
def drink(self):
print ‘%s要喝水‘%self.name
# 创建猫对象
tom = Cat()
# 可以使用 .属性名 利用赋值语句就可以了
#tom.name = ‘Tom‘
tom.eat()
tom.name = ‘Tom‘
tom.drink()
print tom
# lazy_cat = Cat()
# lazy_cat.name = ‘miaomiao‘
# lazy_cat.eat()
# lazy_cat.drink()
2.内置方法
初始化方法:__init__是python对象的内置方法,在使用类名创建对象的时候自动被调用
__init__方法是专门用来定义一个类具有那些属性和方法的
##如果不用初始化方法,像一些基本属性可能在创建对象以后,还需要对象.属性,这样填写属性,还需要print手动去输出它,添加这个初始化方法,在创建方法之后会主动调用这个方法,将填写的信息添加并且输出
##当初始化方法没有形参变量的时候,方法内部所定义的属性,在利用该类创建对象的时候,创建的所有对象都会拥有该属性
##当初始化方法含有形参变量的时候,在利用该类创建对象的时候,创建的所有对象都会自动调用初始化方法,并且会要求添加相应的对象的属性,如果不添加就执行的话,编译器会报错
__del__方法:对象被从内存中销毁前,会自动调用
__str__方法:返回对象的描述信息 print 对象
__del__方法:在python中,当一个对象被从内存中销毁前(把这个对象从内存中删除掉),会自动调用__del__方法
应用场景:
__del__如果希望在对象被销毁前,再做一些事情,可以考虑一下__del__方法
__str__方法:在python中,使用python输出对象变量,默认情况下,会输出这个变量引用的对象是由哪>一个类创建的对象,以及在内存中的地址(十六进制表示).如果在开发中,希望使用print输出对象变量时,能够打印自定义的内容,就可以利用__str__这个内置方法了
示例:
(1)
class Dog:
def __init__(self,name,weight):
self.name = ‘rourou‘
self.weight = weight
print ‘%s是一个%d斤的狗狗!‘%(self.name,self.weight)
def eat(self):
print ‘%s爱吃肉‘%self.name
def drink(self):
print ‘%s爱喝牛奶‘%self.name
rourou = Dog(‘rourou‘,10)
rourou.eat()
rourou.drink()
print rourou
(2)
class Dog:
def __init__(self,name,weight):
self.name = name
self.weight = weight
print ‘%s是一个%d斤重的狗狗!‘%(self.name,self.weight)
def __del__(self):
print ‘内存信息被删除之前的调用!‘
def __str__(self):
return ‘我是肉肉!‘
dog = Dog(‘rourou‘,10)
print ‘=========‘
print dog
# tom是一个全局变量
# 所以当我们的代码全部执行完之后,系统才会把tom这个对象进行回收
tom = Cat(‘Tom‘)
print tom
# print tom.name
# # del关键字,可以从内存中删除一个对象,del关键字自己调用了__del__方法
# del tom
# print ‘*‘ * 50
生命周期
一个对象从调用类名()创建,声明周期开始
一个对象的__del__方法一旦被调用,生命周期就结束
在对象的生命周期内,可以访问对象的属性,调用对象的方法
3.私有属性和私有方法
(1)私有属性和私有方法:在属性或方法前加两个下划线 ‘__‘,声明该方法是私有方法或者属性,不能在类的外部调用。在类的内部可以调用
私有属性 就是 对象 不希望公开的 属性
私有方法 就是 方法 不希望公开的 方法
(2)应用场景及定义方式:
应用场景:
在实际开发中,对象的某些属性或方法可能只希望在对象的内部使用,而不希望在外部被访问到
定义方法:
在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法
示例:
class Women:
def __init__(self,name):
self.name = name ##这是一个公有属性
self.__age = 18 ##这是一个私有属性
def __secret(self): ##这是一个私有方法
print ‘%s 的年龄是 %d‘ %(self.name,self.__age)
lily = Women(‘lily‘)
print lily.name
# 私有属性,外界不能直接访问
print lily.age
# 私有方法,外界不能直接调用
lily.__secret()
结果:
会出现报错,显示没有这个属性,所以说,私有属性和方法,在类的外部不能被调用
lily
Traceback (most recent call last):
File "/home/kiosk/PycharmProjects/王芳/day06/私有属性和私有方法.py", line 27, in <module>
print lily.age
AttributeError: Women instance has no attribute ‘age‘
(3)类的私有属性和私有方法
--子类对象不能在自己的方法内部,直接访问父类的私有属性和私有方法
--子类对象可以通过父类的公有方法间接访问到私有属性或私有方法
私有属性,私有方法是对象的隐私,不对外公开,外界以及子类都不能直接访问
私有属性,私有方法常用做一些内部的事情
示例:
class A:
def __init__(self):
# 在初始化方法中定义两个属性,一个公有属性一个私有属性
self.num1 = 100 #公有属性
self.__num2 = 200 #私有属性
def __test(self):
print ‘私有方法 %d %d‘ % (self.num1, self.__num2)
##如果要查看私有的属性和方法,可以在类A中定义一个公有方法,然后在公有方法中调用私有的方法和属性,再print就可以输出私有的属性和方法。再在子类直接调用这个公有方法就可以了
def test(self):
print ‘父类的共有方法 %d‘ % self.__num2
self.__test()
class B(A):
def demo(self):
# # 在子类的对象方法中,不能访问父类的私有属性
# print ‘访问父亲的私有属性 %d‘ % self.__num2
# # 在子类对象的方法中,不能调用父类的私有方法
# self.__test()
#调用父类的共有方法
self.test()
# 创建一个子类对象
b = B()
b.demo()
# b.test()
# 在外界不能直接访问对象有属性/调用私有方法
# print b.__num2的私
# b.__test()
4.面向对象的三大特征
(1)封装:根据职责将属性和方法封装到一个抽象的类中
(2)继承:实现代码的重用,相同的代码不需要重复的写
(3)多态
5.单继承
继承的概念:子类拥有父类的所有属性和方法
继承的语法
class 类名(父类):
def 子类特有的方法
"""
Cat类是Animal类的子类,Animal类是Cat类的父类,Cat从Animal类继承
Cat类是Animal类的派生类,Animal类是Cat类的基类,Cat类从Animal类派生
"""
class Animal(object):
def eat(self):
print ‘吃‘
def drink(self):
print ‘喝‘
def run(self):
print ‘跑‘
def sleep(self):
print ‘睡‘
class Cat(Animal):
# 子类拥有父类的所有属性和方法
def call(self):
print ‘喵喵‘
class Dog(Animal):
def bark(self):
print ‘旺旺‘
class Hellokitty(Cat):
def speak(self):
print ‘我可以说日语‘
# 创建一个猫对象
fentiao = Cat()
fentiao.eat()
fentiao.drink()
fentiao.run()
fentiao.sleep()
fentiao.call()
# 创建一个hellokitty对象
# kt = Hellokitty()
# kt.speak()
# kt.call()
# 继承的传递性,子类拥有父类的父类的属性和方法
"""
继承的传递性:(爷爷 父亲 儿子)
1.C类从B类继承,B类又从A类继承
2.那么C类就具有B类和A类的所有属性和方法
子类拥有父类以及父类的父类中封装的所有属性和方法
"""
kt.eat()
kt.drink()
kt.run()
kt.sleep()
# 子类继承自父类,可以直接享受父类中已经封装好的方法
# 子类中应该根据自己的职责,封装子类特有的属性和方法
6.多继承
class A:
def test(self):
print ‘A-----test 方法‘
def demo(self):
print ‘A-----demo 方法‘
class B:
def test(self):
print ‘B------test 方法‘
def demo(self):
print ‘B-------demo方法‘
class C(B,A):
"""多继承可以让子类对象,同时具有多个父类的属性和方法"""
"""多继承(A,B)这个,如果两个父类的方法重名的话,哪个放在前面就继承哪个"""
pass
# 创建子类对象
c = C()
c.test()
c.demo()
7.封装
(1)封装是面向对象编程的一大特点
(2)面向对象编程的第一步 将属性和方法封装到一个抽象的类中(为什么说是抽象的,因为类不能直接使用)
(3)外界使用类创建对象,然后让对象调用方法
(4)对象方法的细节都被封装在类的内部
示例:
小明爱跑步
1.小明体重75.0公斤
2.每次跑步会减肥0.5公斤
3每次吃东西体重会增加1公斤
4.小美的体重是45.0公斤
class Person:
def __init__(self,name,weight):
self.name = name
self.weight = weight
def __str__(self):
return ‘我的名字叫 %s 体重是 %.2f‘ %(self.name,self.weight)
def run(self):
print ‘%s 爱跑步‘ %self.name
# 在对象方法的内部,是可以直接访问对象的属性
self.weight -= 0.5
def eat(self):
print ‘%s 吃东西‘ %self.name
self.weight += 1
xx = Person(‘小明‘,75.0)
xx.run()
xx.eat()
print xx
# 同一个类创建出来的多个对象之间,属性互不干扰
xm = Person(‘小美‘,45.0)
xm.run()
xm.eat()
print xm
封装练习:
(1)需求
--房子有户型,总面积和家具名称列表
新房子没有任何家具
--家具有名字和占地面积,其中
床:占4平米
衣柜:占2平米
餐桌:占1.5平米
--将以上三件家具添加到房子中
--打印房子时,要求输出:户型,总面积,剩余面积,家具名称列表
被使用的类应该先开发
就比如:先要将家具定义出来,然后才能往房子里面加
# 创建家具类
class HouseItem:
def __init__(self, name, area):
self.name = name
self.area = area
def __str__(self):
return ‘[%s]占地为 %.2f‘ % (self.name, self.area)
# 创建家具
bed = HouseItem(‘bed‘, 4)
print bed
chest = HouseItem(‘chest‘, 2)
print chest
table = HouseItem(‘table‘, 1.5)
print table
# 创建房子类
class House:
def __init__(self, house_type, area):
# 下面为从外界传递进来的参数
self.house_type = house_type
self.area = area
# 剩余面积不需要从外面传递,内部计算
# 剩余面积 = 总面积 - 家具面积
# 新房子内没有任何家具,剩余面积=总面积
self.free = area
self.item_list = []
def __str__(self):
return ‘户型:%s 总面积:%.2f[剩余面积:%.2f] 家具:%s‘
% (self.house_type, self.area, self.free, self.item_list)
def add_item(self, item):
if item.area >= self.area:
print ‘请重新订购家具‘
else:
print ‘添加成功‘
self.item_list.append(item.name)
self.free -= item.area
# 创建房子
house = House(‘两室一厅‘, 100)
house.add_item(bed)
house.add_item(chest)
house.add_item(table)
print house
(2)需求:
--士兵瑞恩有一把AK47
--士兵可以开火(士兵开火扣动的是扳机)
--枪 能够 发射子弹(把子弹发射出去)
--枪 能够 装填子弹 --增加子弹数量
class Gun:
def __init__(self, name):
# 自己输入枪的型号
self.name = name
# 假设默认的子弹数是10个
self.count = 10
self.free = self.count
def add_zidan(self, num):
if num + self.free > 10:
print ‘子弹数超过10颗!装子弹失败‘
else:
self.free += num
print ‘子弹添加成功!‘
def shoot(self):
if self.free <= 0:
print ‘没有子弹了!‘
else:
self.free -= 1
print ‘开火ing...‘
class Person:
def __init__(self,name):
self.name = name
self.gun = None
def fire(self):
if self.gun == None:
print ‘还没有枪‘
return
print ‘go!‘
self.gun.shoot()
self.gun.add_zidan(1)
ak47 = Gun(‘AK47‘)
ren = Person(‘ryan‘)
#人使用枪
ren.gun = ak47
ren.fire()
print ren
8.重写父类方法
(1).覆盖父类的方法
(2).扩展父类的方法
class Animal:
def eat(self):
print ‘吃‘
def drink(self):
print ‘喝‘
def run(self):
print ‘跑‘
def sleep(self):
print ‘睡‘
class Cat(Animal):
# 子类拥有父类的所有属性和方法
def call(self):
print ‘喵喵‘
class Hellokitty(Cat):
def speak(self):
print ‘我可以说话‘
def call(self):
# 重写父类的方法
print ‘话~~‘
# 调用原本在父类中封装的代码
Cat.call(self)
# 增加其他的子类代码
print ‘#[email protected][email protected]!#!#‘
kt = Hellokitty()
# 如果子类中,重写了父类的方法
# 在运行中,只会调用在子类中重写的父类的方法而不会调用父类的方法
kt.call()
重写的练习:
--在写好的代码Bird类的上面,加入一个唱歌的属性(要增加到默认属性当中)
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
# 如果吃过了就不饿了
if self.hungry:
print ‘吃东西ing。。。‘
self.hungry = False
else:
print ‘No,thanks!‘
错误代码:
class songBird(Bird):
def __init__(self):
self.sound = ‘squawk!‘
def sing(self):
print self.sound
lb = songBird()
lb.eat()
lb.sing()
print lb
##这就相当于是songBird的初始化方法将原本的代码的初始化方法覆盖了,因此就没有了 self.hungry = True 这行代码,因此下面的判断就不能够执行下去
##正确的代码应该是,继承了父类,重写并且调用父类的被重写的方法,这样就相当于是在不更改源代码的同时,增加了默认的属性
正确代码:
class songBird(Bird):
def __init__(self):
self.sound = ‘squawk!‘
Bird.__init__(self) ##这条语句就是调用父类的方法
def sing(self):
print self.sound
lb = songBird()
lb.eat()
lb.sing()
print lb
9.新式类和旧式(经典)类
object是Python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看
新式类:以object为基类的类,推荐使用
经典类:不以object为基类的类,不推荐使用
在python3.X中定义的类时,如果没有指定父类,会默认使用object作为基类--python3.x中定义的类都是新式类
在python2.x中定义类时,如果没有指定父类,则不会以object作为基类
####推荐使用新式类#############
新式类和旧式类在多继承时---会影响到方法的搜索顺序
为保证编写的代码能够同时在python2.x和python3.x运行
今后在定义类时,如果没有父类,建议统一继承自object
10.综合练习
图书管理系统
图书管理系统
1.查询
2.增加
3.借阅
4.归还
5.退出
以上是关于Python——创建类和对象的主要内容,如果未能解决你的问题,请参考以下文章