面向对象编程基础
面向对象的思想:
面向对象和面向过程的思想有着本质上的区别,作为面向对象的思维来说,当你拿到一个问题时,你分析这个问题不再是第一步先做什么,第二步再做什么,这是面向过程的思维,你应该分析这个问题里面有哪些类和对象,这是第一点,然后再分析这些类和对象应该具有哪些属性和方法。这是第二点。最后分析类和类之间具体有什么关系,这是第三点。
面向对象有一个非常重要的设计思维:合适的方法应该出现在合适的类里面。
三大特性:封装 继承 多态
类和对象
关系:类是对象的蓝图和模板,而对象是类的实例
定义类:
class Student(object):
# __init__是一个特殊方法用于在创建对象时进行初始化操作
# 通过这个方法我们可以为学生对象绑定name和age两个属性
def __init__(self,name,age):
self.name = name
self.age = age
def study(self,course_name):
print('%s正在学习%s.'%(self.name,course_name))
def watch_tv(self):
if self.age<18:
print('%s只能观看动画片。'%self.name)
else:
print('%s正在观看大电影'%self.name)
def main():
stu1=Student('小米',25)
stu1.study('Python程序设计')
stu1.watch_tv()
stu2=Student('小成都',16)
stu2.study('思想品德')
stu2.watch_tv()
if __name__ == '__main__':
main()
=======================================
小米正在学习Python程序设计.
小米正在观看大电影
小成都正在学习思想品德.
小成都只能观看动画片。
访问可见性:
1.public公共的
2.protected受保护的
3.private私有的(在给属性命名时可以用两个下划线作为开头)
class Test:
def __init__(self,name):
self.__name=name
def __A(self):
print(self.__name)
print('__A')
def main():
test=Test('hello')
test.__A()
print(test.__name)
if __name__== '__main__':
main()
===========================
AttributeError Traceback (most recent call last)
<ipython-input-12-d7ac72280ea7> in <module>
10 print(test.__name)
11 if __name__== '__main__':
---> 12 main()
<ipython-input-12-d7ac72280ea7> in main()
7 def main():
8 test=Test('hello')
----> 9 test.__A()
10 print(test.__name)
11 if __name__== '__main__':
AttributeError: 'Test' object has no attribute '__A'
练习:
定义一个描述数字时钟:
class Clock(object):
def __init__(self,hour=0,minute=0,second=0):
self._hour =hour
self._minute =minute
self._second = second
def run(self):
self._second +=1
if self._second ==60:
self._second =0
self._minute +=1
if self._minute ==60:
self._minute = 0
self._hour += 1
if self._hour ==24:
self._hour =0
def __str__(self):
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second)
def main():
clock =Clock(23,59,58)
while True:
print(clock)
sleep(1)
clock.run()
if __name__=='__main__':
main()
====================
23:59:58
面向对象进阶
@property装饰器
将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作。如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问既安全又方便。
class Person(object):
def __init__(self,name,age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
def play(self):
if self._age <=16:
print('%s正在玩飞行棋'%self._name)
else :
print('%s正在玩斗地主'%self.name)
def main():
person = Person('小明',120)
person.play()
if __name__=='__main__':
main()
=============================
小明正在玩斗地主
__slots__魔法
Python是一门动态语言。通常,动态语言允许我们在程序运行时给对象绑定新的属性或方法,当然也可以对已经绑定的属性和方法进行解绑定。但是如果我们需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义__slots__变量来进行限定。需要注意的是__slots__的限定只对当前类的对象生效,对子类并不起任何作用。
class Person(object):
# 限定Person对象只能绑定_name, _age和_gender属性
__slots__ = ('_name', '_age', '_gender')
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def play(self):
if self._age <= 16:
print('%s正在玩飞行棋.' % self._name)
else:
print('%s正在玩斗地主.' % self._name)
def main():
person = Person('王大锤', 22)
person.play()
person._gender = '男'
if __name__=='__main__':
main()
======================
王大锤正在玩斗地主.
继承和多态
提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力,在实际开发中,我们经常会用子类对象去替换掉一个父类对象,这是面向对象编程中一个常见的行为,对应的原则称之为里氏替换原则。
class Person(object):
"""人"""
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def play(self):
print('%s正在愉快的玩耍.' % self._name)
def watch_av(self):
if self._age >= 18:
print('%s正在观看爱情动作片.' % self._name)
else:
print('%s只能观看《熊出没》.' % self._name)
class Student(Person):
"""学生"""
def __init__(self, name, age, grade):
super().__init__(name, age)
self._grade = grade
@property
def grade(self):
return self._grade
@grade.setter
def grade(self, grade):
self._grade = grade
def study(self, course):
print('%s的%s正在学习%s.' % (self._grade, self._name, course))
class Teacher(Person):
"""老师"""
def __init__(self, name, age, title):
super().__init__(name, age)
self._title = title
@property
def title(self):
return self._title
@title.setter
def title(self, title):
self._title = title
def teach(self, course):
print('%s%s正在讲%s.' % (self._name, self._title, course))
def main():
stu = Student('小明', 15, '初三')
stu.study('数学')
stu.watch_av()
t = Teacher('老王', 38, '老屌丝')
t.teach('Python程序设计')
t.watch_av()
if __name__ == '__main__':
main()
======================
初三的小明正在学习数学.
小明只能观看《熊出没》.
老王老屌丝正在讲Python程序设计.
老王正在观看爱情动作片.