Python学习第十四课-面向对象四
一、多态
1.1 简介
-
多态是面向对象的三大特性之一。从字面理解就是多种形态:一个对象可以以不同形态去呈现
-
面向对象三大特性:
- 1.封装 确保对象中数据的安全
- 2.继承 保证了对象的扩展性
- 3.多态 保证了程序的灵活性
-
Python中多态的特点:
- 1、只关心的实例方法是否同名,不关心对象所属的类型;
- 2、对象所属的类之间,继承关系可有可无;
- 3、多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性较强;
- 4、多态是调用方法的技巧,不会影响到类的内部设计。
1.2 练习
class Person(object):
name = "人"
def speak(self):
print("{}会说话".format(self.name))
class Doctor(Person): # 括号里是你要继承的父类的名称
name = '医生'
def speak(self):
print("{}会安抚病人".format(self.name))
def cure(self):
print("{}会治病".format(self.name))
class Police(Person):
name = '警察'
def speak(self):
print("{}会维护治安".format(self.name))
def method(obj):
obj.speak()
a = Police()
method(a)
b = Doctor()
method(b)
'''
警察会维护治安
医生会安抚病人
'''
class Grandpa(object):
def money(self):
print('这是爷爷的钱')
class Father(Grandpa):
def money(self):
super().money() # 注释的话,儿子就继承不了爷爷的钱
print('这是父亲的钱')
class Son(Father):
def money(self):
super().money() # 只能继承上一级类
print('这是儿子的钱')
def method(obj):
obj.money()
grandpa = Grandpa()
father = Father()
son = Son()
# method(grandpa) # 这是爷爷的钱
#method(father) # 这是爷爷的钱 这是父亲的钱
method(son)
'''
这是爷爷的钱
这是父亲的钱
这是儿子的钱
'''
二、属性和方法
2.1类属性
- 修改属性:对象. 属性名 = 属性值
- 类属性:直接在类中定义的属性是类属性
- 类属性可以通过类或类的实例访问到。但是类属性只能通过类对象来修改,不能通过实例对象来修改,方法通过实例对象修改
2.2 练习
class A(object):
num = 0
a = A()
print(a.num) # 通过实例对象访问类属性 # 0
print(A.num) # 通过类对象访问类属性 # 0
a.num = 10 # 创建一个新的同名的num的实例属性
print(a.num) # 实例属性 # 10
print(A.num) # 类属性 0
A.num = 10 # 修改类属性
print(a.num)
print(A.num)
'''
0
0
10
0
10
10
'''
2.3 实例属性
- 实例属性:通过实例对象添加的属性属于实例属性
- 实例属性只能通过实例对象来访问和修改,类对象无法访问修改
2.4 练习
class A(object):
num = 0
a = A()
print(a.num) # 通过实例对象访问类属性 # 0
print(A.num) # 通过类对象访问类属性 # 0
a.name = '紫紫' # 创建一个新的同名的num的实例属性
print(a.name) # 实例属性 # 紫紫
# print(A.name) # AttributeError: type object 'A' has no attribute 'name'
'''
0
0
紫紫
'''
2.5 实例方法
- 实例方法:在类中定义,以self为第一个参数的方法都是实例方法
- 实例方法在调用时,Python会将调用对象以self传入
- 实例方法可以通过类实例和类去调用
- 当通过实例调用时,会自动将当前调用对象作为self传入
- 当通过类调用时,不会自动传递self,我们必须手动传递self(加参数)
2.6 练习
class Person(object):
name = "人"
def speak(self):
print("{}会说话".format(self.name))
class Doctor(Person): # 括号里是你要继承的父类的名称
name = '医生'
def speak(self):
print("{}会安抚病人".format(self.name))
def cure(self):
print("{}会治病".format(self.name))
class Police(Person):
name = '警察'
def speak(self):
print("{}会维护治安".format(self.name))
def method(obj):
obj.speak()
a = Police()
a.speak()
Police.speak(a)
#Police.speak() #TypeError: speak() missing 1 required positional argument: 'self'
'''
警察会维护治安
警察会维护治安
'''
2.7 类方法
- 类方法:在类的内容以==@classmethod 来修饰==的方法属性类方法
- 类方法第一个参数是cls也会自动被传递,cls就是当前的类对象。
- 类方法和实例方法的区别:
- 1.实例方法的第一个参数是self,类方法的第一个参数是cls
- 2.类方法可以通过类去调用,也可以通过实例调用
2.8 练习
class Person(object):
name = "人"
def speak(self):
print("{}会说话".format(self.name))
class Doctor(Person): # 括号里是你要继承的父类的名称
name = '医生'
def speak(self):
print("{}会安抚病人".format(self.name))
def cure(self):
print("{}会治病".format(self.name))
class Police(Person):
name = '警察'
def speak(self):
print("{}会维护治安".format(self.name))
@classmethod
def run(cls):
print("{}跑步飞快,可以轻易追上小偷".format(cls.name))
def method(obj):
obj.speak()
a = Police()
a.speak()
Police.speak(a)
#Police.speak() #TypeError: speak() missing 1 required positional argument: 'self'
a.run()
Police.run()
'''
警察会维护治安
警察会维护治安
警察跑步飞快,可以轻易追上小偷
警察跑步飞快,可以轻易追上小偷
'''
2.9 静态方法
- 在类中用==@staticmethod来修饰==的方法属于静态方法
- 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例调用
- 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数
- 静态方法一般都是些工具方法,和当前类无关
2.10 练习
class Person(object):
name = "人"
def speak(self):
print("{}会说话".format(self.name))
class Doctor(Person): # 括号里是你要继承的父类的名称
name = '医生'
def speak(self):
print("{}会安抚病人".format(self.name))
def cure(self):
print("{}会治病".format(self.name))
class Police(Person):
name = '警察'
def speak(self):
print("{}会维护治安".format(self.name))
@classmethod
def run(cls):
print("{}跑步飞快,可以轻易追上小偷".format(cls.name))
@staticmethod
def staticmethod():
print('我是静态方法') # 静态方法,跟该类没关系,只是放到类里面,可以调用
def method(obj):
obj.speak()
a = Police()
#Police.speak() #TypeError: speak() missing 1 required positional argument: 'self'
a.run()
Police.run()
a.staticmethod()
Police.staticmethod()
'''
警察会维护治安
警察会维护治安
警察跑步飞快,可以轻易追上小偷
警察跑步飞快,可以轻易追上小偷
'''
三、单例模式
- 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
3.1 new()方法
- 当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式
-
练习:__new__()方法用于创建与返回一个对象。在类准备将自身实例化时调用。
以下代码打印输出的顺序? C A.__init__,__new__ B.__init__ C.__new__ D.__new__,__init__
class Demo(object):
def __init__(self): #__init__()方法在对象创建的时候,自动调用
print("__init__")
def __new__(cls, *args, **kwargs): # __new__()方法用于创建对象
print("__new__")
d = Demo()
'''
__new__
'''
执行顺序:
__new__()方法用于创建对象 __init__()方法在对象创建的时候,自动调用 但是此处重写了父类的__new__()方法,覆盖了父类__new__()创建对象的功能,所以对象并没有创建成功。所以仅执行__new__()方法内部代码。
3.2 练习
class single(object):
obj = None
def __new__(cls, *args, **kwargs):
if cls.obj is None:
cls.obj = super().__new__(cls)
return cls.obj
else:
return cls.obj
s1 = single()
s2 = single()
print(s1)
print(s2)
print(s1 is s2)
'''
<__main__.single object at 0x0000021C64510B00>
<__main__.single object at 0x0000021C64510B00>
True
'''
四、模块
4.1 简介
- 模块化指一个完整的程序分解成一个个的小模块,通过将模块组合,来搭建出一个完整的程序
- 模块化的特点:方便开发、方便维护、模块可以复用
4.2 模块的创建
- 在Python当中一个py文件就是一个模块
- 在一个模块中引入外部模块:import 模块名(模块名就是py文件)
- 可以引入同一个模块多次,但是模块的实例只会创建一次
- import 模块名
- 在一个模块内部都有一个__name__。通过它我们可以获取模块的名字。
- 如果py文件直接运行时,那么__name__默认等于字符串’main’。 name__属性值为__main(命名空间locals()的第一句“name : main”)的模块是主模块。一个程序中只有一个主模块
4.3 模块的使用
- 访问模块中的变量 语法是 模块名.变量名
- 访问模块中的函数 语法是 模块名.函数名
- 访问模块中的对象 语法是 模块名.对象名
- 我们也可以引入模块中部分内容 语法是 from 模块名 import 变量,变量…
- 还有一种引入方式 语法 from 模块名 import 变量 as 别名(当导入的东西和当前模块冲突了,那么可以取别名)
需要掌握的模块: os, sys, time, random
4.4 import 语句
- 想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:
import module1[, module2[,... moduleN]
# @File : support.py
# @Description :
def print_func(par):
print("Hello : ", par)
return
# @File : test.py
# @Description :
# 导入模块
import support
# 现在可以调用模块里包含的函数了
support.print_func("Runoob")
'''
Hello : Runoob
'''
-
当我们使用import语句的时候,Python解释器是怎样找到对应的文件的呢?
-
这就涉及到Python的搜索路径,搜索路径是由一系列目录名组成的,Python解释器就依次从这些目录中去寻找所引入的模块。
-
这看起来很像环境变量,事实上,也可以通过定义环境变量的方式来确定搜索路径。
-
搜索路径是在Python编译或安装的时候确定的,安装新的库应该也会修改。搜索路径被存储在sys模块中的path变量