1. 多态
- 多态是面向对象的三大特性之一。从字面理解就是多种形态
- 个对象可以以不同形态去呈现
- 面向对象三大特性
- 封装 确保对象中数据的安全
- 继承 保证了对象的扩展性
- 多态 保证了程序的灵活性
- Python中多态的特点
- 1、只关心对象的实例方法是否同名,不关心对象所属的类型;
- 2、对象所属的类之间,继承关系可有可无;
- 3、多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强;
- 4、多态是调用方法的技巧,不会影响到类的内部设计。
class A(object):
def __init__(self, name):
self.name = name
def speak(self):
print('大家好,我是%s' % self.name)
class B(object):
def __init__(self, name):
self.name = name
def speak(self):
print('大家好,我是%s' % self.name)
a = A('刘亦菲')
b = B('周慧敏')
运行结果:
大家好,我是刘亦菲
大家好,我是周慧敏
class Duck(object):
def fly(self):
print('鸭子沿着地面飞起来了')
class Plane(object):
def fly(self):
print('飞机在云层穿梭')
class Swan(object):
def fly(self):
print('天鹅在空中翱翔')
def fly(obj):
obj.fly()
duck = Duck()
swan = Swan()
plane = Plane()
fly(duck)
fly(swan)
fly(plane)
class Grandpa(object):
def money(self):
print('这是爷爷的钱')
class Father(Grandpa):
def money(self):
super().money()
print('这是爸爸的钱')
class Mother(Grandpa):
def money(self):
super().money()
print('这是妈妈的钱')
def money(obj):
obj.money()
g = Grandpa()
f = Father()
m = Mother()
money(g)
money(f)
money(m)
运行结果:
鸭子沿着地面飞起来了
天鹅在空中翱翔
飞机在云层穿梭
这是爷爷的钱
这是爷爷的钱
这是爸爸的钱
这是爷爷的钱
这是妈妈的钱
2. 属性和方法
2.1属性
- 类属性,直接在类中定义的属性是类属性
- 类属性可以通过类或类的实例访问到。但是类属性只能通过类对象来修改,无法通过实例对象修改
- 实例属性 通过实例对象添加的属性属于实例属性
- 实例属性只能通过实例对象来访问和修改,类对象无法访问修改
# 类属性和实例属性
# 类属性:直接定义在类中的属性
# 类属性可以通过类和实例对象来调用
# 类属性只能通过类对象来修改,不能通过实例对象来修改
# num = 0
class A(object):
num = 0
def __init__(self, name):
self.name = name # 这属性也是实例属性
print(self)
def speak(self): # 实例方法
print('大家好,我是%s' % self.name)
@classmethod # 类方法 用了个类装饰器实现类方法
def run(cls):
print('我能跑')
# def study(cls): 没有用类装饰器,其实也是个实例方法 ,只是没有规范用self参数,用了其他而已
# print('我是什么方法')
@staticmethod
def static(): # 功能方法 工具方法 类对象和实例对象都可以调用 其实就是保存在类中的函数与类无关
print('我是静态方法')
a = A('刘亦菲')
print(a)
# 实例属性:通过实例对象来添加的属性就是实例属性,只能通过实例对象来调用,不能使用类对象来调用
# a.num = 10 # 实例属性
print(A.num) # 使用类对象来调用属性
print(a.num) # 使用实例对象来调用属性
print(a.name)
# print(A.name) # 这里会报错 实例属性不能用类对象来调用
# 方法
# 实例方法:实例方法类对象和实例对象都可以调用 ,但是类对象需要传递一个实例参数
print(a.speak) # print(A.speak()) speak 实例方法不能用类对象来调用
print(A.speak(a)) # 可以加个实例对象参数 来调用实例方法
# 类方法 实例对象和类对象都可以调用
# a.run()
# A.run()
# a.study()
# A.study()
a.static()
A.static()
相应运行结果:
0
0
刘亦菲
<bound method A.speak of <__main__.A object at 0x0000016A96D60588>>
大家好,我是刘亦菲
None
我是静态方法
我是静态方法
2.2 方法
- 在类中定义,以self为第一个参数的方法都是实例方法
- 实例方法在调用时,Python会将调用对象以self传入
- 实例方法可以通过类实例和类去调用
- 当通过实例调用时,会自动将当前调用对象作为self传入
- 当通过类调用时,不会自动传递self,我们必须手动传递self
- 类方法 在类的内容以@classmethod 来修饰的方法属性类方法
- 类方法第一个参数是cls 也会自动被传递。cls就是当前的类对象
- 类方法和实例方法的区别,实例方法的第一个参数是self,类方法的第一个参数是cls
- 类方法可以通过类去调用,也可以通过实例调用
- 静态方法
- 在类中用@staticmethod来修饰的方法属于静态方法
- 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例调用
- 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数
- 静态方法一般都是些工具方法,和当前类无关
3. 单例模式
# class Demo(object):
# def __init__(self):
# print("__init__")
#
# @staticmethod
# def __new__(cls, *args, **kwargs): # __new__方法是静态方法
# super().__new__(cls)
# print("__new__")
# return super().__new__(cls) # cls 指 Demo return super().__new__(cls) 等价于return super().__new__(demo)
#
#
# d = Demo()
# d1 = Demo()
# print(d)
# print(d1)
"""
做一个判断:1. 如果实例存在,我们就不再调用super这个方法,而是直接返回之前的那个实例对象
2. 如果不存在,就调用super方法创建实例并且返回
"""
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
s = Single()
s1 = Single()
print(s)
print(s1)
运行结果:
<__main__.Single object at 0x000002238ABA98D0>
<__main__.Single object at 0x000002238ABA98D0>
new()方法
new()方法用于创建与返回一个对象。在类准备将自身实例化时调用。
练习
以下代码打印输出的顺序?
A.__init__,__new__
B.__init__
C.__new__
D.__new,__init__
class Demo(object):
def __init__(self):
print("__init__")
def __new__(cls, *args, **kwargs):
print("__new__")
d = Demo()
注意
__new__()方法用于创建对象
__init__()方法在对象创建的时候,自动调用
但是此处重写了父类的__new__()方法,覆盖了父类__new__()创建对象的功能,所以对象并没有创建成功。所以仅执行__new__()方法内部代码
对象创建执行顺序
① 通过__new__()方法创建对象
② 并将对象返回,传给__init__()
练习
在自定义类中实现创建对象
思路
• 重写父类__new__()方法
• 并且在该方法内部,调用父类的__new__()方法
class Demo(object):
def __init__(self):
print("__init__")
def __new__(cls, *args, **kwargs):
print("__new__")
return super().__new__(cls)
d = Demo()
运行结果:
__new__
__init__
注意
• 在创建对象时,一定要将对象返回,在会自动触发__init__()方法
• __init__()方法当中的self,实际上就是__new__返回的实例,也就是该对象
__init__()与__new__()区别
• __init__实例方法,__new__静态方法
• __init__在对象创建后自动调用,__new__创建对象的方法
- 单例模式 单例模式介绍 单例模式是一种常用的软件设计模式。也就是说该类只包含一个实例。
- 通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。
- 如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
- 通常应用在一些资源管理器中,比如日志记录等。
- 单例模式实现 思路 • 当对象不存在时,创建对象 • 当对象存在时,永远返回当前已经创建对象
class single(object):
__isinstance = None
def __new__(cls, *args, **kwargs):
if cls.__isinstance is None:
cls.__isinstance = super().__new__(cls)
return cls.__isinstance
else:
return cls.__isinstance
a = single()
b = single()
print(id(a))
print(id(b))
运行结果:
2666086204416
2666086204416
4. 模块
模块化指将一个完整的程序分解成一个个的小模块
通过将模块组合,来搭建出一个完整的程序
模块化的特点
• 方便开发
• 方便维护
• 模块可以复用
4.1. 模块的创建
• 在Python当中一个py文件就是一个模块
• 在一个模块中引入外部模块 import 模块名(模块名就是py文件)
• 可以引入同一个模块多次,但是模块的实例只会创建一次
• import 模块名 as 模块别名
• 在一个模块内部都有一个__name__。通过它我们可以获取模块的名字
• 如果py文件直接运行时,那么__name__默认等于字符串’main’。__name__属性值为__main__的模块是主模块。一个程序中只有一个主模块
# test1
print('这是我的第一个模块')
# a = 1
# b = 2
#
#
# def fun():
# print('我是fun')
#
#
print(__name__)
# s = locals()
# print(s)
class A():
def __init__(self, name):
self.name = name
print(self.name)
if __name__ == '__main__': # main函数 程序的入口函数 不是在当前模块运行的程序,那么这个程序就不会运行
b = A('周慧敏')
运行结果
D:\yiyong\venv\Scripts\python.exe D:/yiyong/day14/test1.py
这是我的第一个模块
__main__
周慧敏
# 模块的创建
import test1
import test1
import test1 as test
# from test1 import fun
from test1 import *
# print(test)
# fun()
# print(a)
# print(b)
a = A('刘亦菲')
相应运行结果
这是我的第一个模块
test1
刘亦菲
4.2模块的使用
- 访问模块中的变量 语法是 模块名.变量名
- 访问模块中的函数 语法是 模块名.函数名
- 访问模块中的对象 语法是 模块名.对象名 •
- 我们也可以引入模块中部分内容 语法 from 模块名 import 变量,变量…
- 还有一种引入方式 语法 from 模块名 import 变量 as 别名
描述 random() 方法返回随机生成的一个实数,它在[0,1)范围内
语法 以下是 random() 方法的语法:
注意:random()是不能直接访问的,需要导入 random 模块,然后通过 random 静态对象调用该方法。
参数
无
返回值
返回随机生成的一个实数,它在[0,1)范围内。
实例
以下展示了使用 random() 方法的实例:
Python time time()方法
描述 Python time time() 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。语法 time()方法语法:
参数 NA。
返回值 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。实例 以下实例展示了 time() 函数的使用方法:
以上实例输出结果为
概述 os.pardir() 获取当前目录的父目录(上一级目录),以字符串形式显示目录名。
注意: Windows 和 POSIX 返回 …。
语法 pardir()方法语法格式如下:
参数
无。返回值
返回当前目录的父目录,默认值为 …。
实例
以下实例演示了 pardir() 方法的使用:
打印当前目录的父目录
import os
# 当前工作目录
path = os.getcwd()
print("当前工作目录: ", path)
# 父目录
parent = os.path.join(path, os.pardir)
# 父目录
print("\n父目录:", os.path.abspath(parent))
运行结果:
D:\yiyong\venv\Scripts\python.exe D:/yiyong/day14/os模块.py
当前工作目录: D:\yiyong\day14
父目录: D:\yiyong
sys模块
Python的sys模块提供访问由解释器使用或维护的变量的接口,并提供了一些函数用来和解释器进行交互,操控Python的运行时环境。
下面就来详细介绍下该模块中常用的属性和方法。
① 动态对象
sys.argv 传递给程序的命令行参数列表;其中,sys.argv[0]表示脚本名称,各个参数均为字符串类型。
写一个脚本,内容如下
import sys
print('参数个数为:', len(sys.argv), '个参数。')
print('参数列表:', str(sys.argv))
print('脚本名:', str(sys.argv[0]))
运行结果:
参数个数为: 1 个参数。
参数列表: ['D:/yiyong/day14/sys_test1.py']
脚本名: D:/yiyong/day14/sys_test1.py
sys.path 模块的搜索路径;sys.path[0] 表示当前脚本所在目录
在交互模式下,sys.path[0] 返回空字符串。
02 静态对象
sys.builtin_module_names 当前解释器所有内置模块的名称
sys.copyright 包含解释器版权相关信息的字符串
sys.exec_prefix 用于查找特定于当前机器的python库的路径前缀
sys.executable Python解释器可执行文件的绝对路径
sys.float_info 包含有关浮点数实现的信息的结构序列
sys.float_repr_style 表示浮点数的repr()方法的输出样式的字符串
sys.hash_info 包含哈希算法相关信息的结构序列
sys.hexversion 对sys.version_info中包含的版本信息进行编码后使用十六进制表示的整数
sys.implementation 包含有关Python实现的相关信息
sys.int_info 包含有关整形实现的信息的结构序列
sys.maxsize 返回字符串、列表、字典和其他内置类型的最大长度
sys.maxunicode 返回能够表示的最大Unicode码点的整数值
sys.platform 返回平台标识符字符串
sys.prefix 返回安装平台无关Python文件的目录
sys.thread_info 包含有关线程实现的信息的结构序列
sys.version 表示当前解释器版本的字符串
sys.version_info 当前解释器版本的命名元组
sys.byteorder 本机的字节排序方式,little表示小尾,big表示大尾
sys.api_version 返回表示Python解释器的C语言版本API的整数
03 方法
sys.displayhook(p_object) 解释器以交互模式运行时,调用该函数会打印表达式的结果
sys.excepthook(type, value, traceback) 发生未捕获的异常时将调用该函数 其中,type是异常类,value是异常的实例, traceback是回溯对象。默认行为是打印该异常并回溯到标准错误。不过,可以重新定义该函数来实现另一种处理未捕获异常的方法(在诸如调试器或者CGI脚本这样的专门的应用程序中可能会用到)。
sys.exit(n) 通过引发SystemExit异常来退出当前程序
n是一个表示状态码的整数退出码。0值表示正常(默认值),非零值表示异常。
如果n指定为一个非整数值,则将它打印到sys.stderr并使用退出码1退出
sys.getdefaultencoding() 返回Unicode实现所使用的默认字符串编码格式
sys.getfilesystemencoding 返回用于将Unicode文件名转换成操作系统使用的文件名时所用的编码格式
sys.getfilesystemencodeerrors() 返回将Unicode文件名转换成操作系统使用的文件名时的错误模式
sys.getdlopenflags() 返回调用C函数 dlopen 时使用的标志参数的值。
sys.getprofile()返回由sys.setprofile(function)设置的系统配置函数
sys.getcheckinterval() 返回由sys.setcheckinterval()函数设置的检查异步事件的频率 >
sys.getrefcount(obj) 返回对象obj的引用计数