Python复习笔记(五)面向对象
1. __init__方法
# 1. 为对象在内存 中分配空间 -- 创建对象
# 2. 为对象属性 设置初始值 -- 初始化方法(init)+--------------
# 3. __init__: 专门用来定义一个类 具有哪些属性的方法!
class Cat:
def __init__(self):
# self.属性名 = 属性的初始值
self.name = "TOM"
# print("这是一个初始化方法")
def eat(self):
print("%s 吃鱼" % self.name) # 使用类名()创建对象的时候会自动调用初始化方法__init__
tom = Cat()
print(tom.name)
TOM 我去了
TOM
2. 利用参数设置属性初始值
# 1. 为对象在内存 中分配空间 -- 创建对象
# 2. 为对象属性 设置初始值 -- 初始化方法(init)
# 3. __init__: 专门用来定义一个类 具有哪些属性的方法!
class Cat:
def __init__(self, new_name):
# self.属性名 = 属性的初始值
self.name = new_name
# print("这是一个初始化方法")
def eat(self):
print("%s 吃鱼" % self.name) # 使用类名()创建对象的时候会自动调用初始化方法__init__
tom = Cat("TOM")
print(tom.name) lazy_Cat = Cat("Lazy")
lazy_Cat.eat()

3. __del__方法
class Cat:
def __init__(self, new_name):
# self.属性名 = 属性的初始值+
self.name = new_name
print("%s 我来了" % self.name)
def eat(self):
print("%s 吃鱼" % self.name) def __del__(self):
print("%s 我去了" % self.name) # 使用类名()创建对象的时候会自动调用初始化方法__init__
tom = Cat("TOM")
print(tom.name) print("-"*50)
TOM 我来了
TOM
--------------------------------------------------
TOM 我去了
4. __str__方法
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 22 16:35:56 2019 @author: Douzi
""" class Cat:
def __init__(self, new_name):
# self.属性名 = 属性的初始值+
self.name = new_name
print("%s 我来了" % self.name)
def eat(self):
print("%s 吃鱼" % self.name) def __del__(self):
print("%s 我去了" % self.name) def __str__(self):
# 必须返回一个字符串
return "我是小猫[%s]" % self.name # 使用类名()创建对象的时候会自动调用初始化方法__init__
tom = Cat("TOM")
print(tom)
TOM 我来了
我是小猫[TOM]
TOM 我去了
5. 身份运算符
用于 比较 两个对象的 内存地址 是否一致—是否是对同一个对象的引用
- 在Python中针对 None 比较时,建议使用 is 判断
- is:例,x is y, 类似 id(x) == id(y))
- is not:例,x is not y, 类似 id(x) != id(b)
注意: is: 判断两个对象的引用是否一致; ==:判断两个对象的值是否一样

6. 私有属性和私有方法: __secret
class Women:
def __init__(self, name):
self.name = name
self.__age = 18
def __secret(self):
print("%s 的年龄是 %d" % (self.name, self.__age))
def say(self):
self.__secret()
xiaofang = Women("小芳")
# 私有属性不能被直接访问
# print(xiaofang.age)
# 在对象的方法内部可以访问
# 私有方法同样不可以在外界方法
#xiaofang.__secret()
xiaofang.say()
7. 伪私有属性和私有方法(不推荐使用)
class Women:
def __init__(self, name):
self.name = name
self.__age = 18
def __secret(self):
print("%s 的年龄是 %d" % (self.name, self.__age))
def say(self):
self.__secret()
xiaofang = Women("小芳")
# 伪私有方法
print(xiaofang._Women__age)
xiaofang._Women__secret()
8. 继承
8.1 单继承
8.1.1. 重新实现父类方法
8.1.2. 调用父类方法: super().funName()
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 22 19:23:57 2019 @author: Douzi
""" class Animal:
def eat(self):
print("吃")
def drink(self):
print("喝")
def run(self):
print("跑")
def sleep(self):
print("睡") class Dog(Animal): def bark(self):
print("www") class XiaoTianQuan(Dog):
def fly(self):
print("飞") def bark(self):
print("叫的跟神一样")
# 使用super(). 调用原本在父类中封装的方法
super().bark() # 父类名.方法(self). 调用父类中封装方法
Dog.bark(self) dog = Dog()
dog.eat() xiaotian = XiaoTianQuan()
xiaotian.bark()
吃
叫的跟神一样
www
www
注意:
子类对象 不能 在自己方法内部 直接 访问父类的私有属性或私有方法(可以通过父类公共方法访问)
子类对象 在外界可以访问到父类的公有属性和方法
8.2 多继承
概念:子类可以拥有多个父类,并且具有 所有父类 的属性和方法
class A:
def test(self):
print("A class") class B:
def demo(self):
print("B demo") class C(A, B):
pass c = C()
c.test()
c.demo()
注意:父类存在同名属性和方法,少用多继承
- python中的MRO——方法搜索顺序:主要用于 在多继承时判断方法, 属性 的调用路径
- python中针对 类 提供一个 内置属性 __mro__ 可以查看方法搜索顺序
class A:
def test(self):
print("A class") def demo(self):
print("A Demo") class B:
def test(self):
print("B test") def demo(self):
print("B demo") class C(B, A):
pass c = C()
c.test()
c.demo() # 确定C类方法调用顺序
print(C.__mro__)
8.3 推荐使用新式类 class A(object):
9. 多态
9.1 调用相同的父类方法,产生不同的执行结果
- 多态可以 增加代码的 灵活度
- 以 继承 和 重写父类方法 为前提
- 是调用方法的 技巧,不会影响类的内部设计
class Dog(object):
def __init__(self, name):
self.name = name
def game(self):
print("%s 玩耍..." % self.name)
class XiaoTianDog(Dog):
def game(self):
print("%s 飞到天上玩耍..." % self.name)
class Person(object):
def __init__(self, name):
self.name = name
def game_with_dog(self, dog):
print("%s 和 %s 快乐的玩" %(self.name, dog.name))
# 让狗玩耍
dog.game()
# 1.创建一个狗对像
# wangcai = Dog("旺财")
xiaotian = XiaoTianDog("飞天狗")
# 2. 创建一个小明对像
xiaoming = Person("小明")
# 3. 让小明调用和狗玩
# xiaoming.game_with_dog(wangcai)
xiaoming.game_with_dog(xiaotian)
- person 类中只需要让 狗对象 调用game方法,而不关心具体 什么狗
- game方法是在Dog父类中定义的
- 在程序执行时,传入不同的 狗对象 实参,就会产生不同的执行效果
10. 几个注意
10.1 类是一个特殊的对象
- 在运行时候,类 同样会被 加载到内存
- 类对象 在内存中 只有一份,使用一个类 可以创建出 很多个对象实例
- 类对象 还可以拥有自己 的属性 和 方法
- 类属性
- 类方法
通过 类名,可以访问类的属性。
11. 类属性
- 类属性 就是给 类对象 中 定义的 属性
- 通常用来记录 与这个类相关 的特征
- 类属性 不会用于 记录 具体对象的特征
示例需求
- 定义一个工具类
- 每个工具都有自己的name
- 需要知道有多少工具
访问类属性两种方式:
1. 类名.类属性
2. 对象.类属性(不推荐)
class Tool(object):
# 使用赋值语句定义 类属性,记录所有工具对象大数量
count = 0
def __init__(self, name):
self.name = name
Tool.count += 1
tool1 = Tool("斧子")
tool1 = Tool("水桶")
print(Tool.count)
2
12. 类方法
- 类方法 就是针对 类对象 定义的方法
- 在 类方法 内部 可以直接访问 类属性 或者调用其他的 类方法
语法如下;
@classmethod
def 类方法名(cls):
pass
修饰器 @classmethod 来标识,告诉解释器 这是一个类方法
- 类方法 第一个参数 应该是 cls
- 由 哪一个类 调用的方法,方法内的 cls就是 哪一个类的引用
- 这个参数 和 实例方法 的 第一参数 是 self 类似
- 提示 使用其他名称也可以,不过习惯使用 cls
- 通过 类名。调用 类方法,调用方法时,不需要传递 cls 参数
- 在方法内部:
- 可以通过 cls,访问 类的属性
- 也可以通过 cls,调用 其他类方法
class Tool(object):
# 使用赋值语句定义 类属性,记录所有工具对象大数量
count = 0
@classmethod
def show_tool_count(cls):
print("工具对象的数量 %d" % cls.count)
def __init__(self, name):
self.name = name
Tool.count += 1
# 创建工具对象
tool1 = Tool("刀")
tool2 = Tool("斧子")
#调用类方法
Tool.show_tool_count()
综合
class Tool(object):
# 使用赋值语句定义 类属性,记录所有工具对象大数量
count = 0
@classmethod
def show_tool_count(cls):
print("工具对象的数量 %d" % cls.count)
def __init__(self, name):
self.name = name
Tool.count += 1
# 创建工具对象
tool1 = Tool("刀")
tool2 = Tool("斧子")
#调用类方法
Tool.show_tool_count()
13. 单例
目的:让类创建的对象,在系统中 只有 唯一的一个实例
13.1 __new__方法
使用 类名() 创建对象时,Python会先调用 __new__方法为对象 分配空间
__new__ 是一个由 Object 基类提供的 内置静态方法,作用:
在内存中为对象分配空间
返回对象的引用
Python的解释器获得对象的引用后,将引用作为第一个参数,传递给 __init__方法
重写 __new__ 方法的代码,非常固定
重写__new__方法 一定要 return super().__new__(cls)
否则 Python解释器 得不到 分配了空间的 对象引用,就不会调用对象的初始化方法
注意: __new__是一个静态方法,在调用时候:主动传递 cls 参数
class MusicPlayer(object):
def __new__(cls, *args, **kwargs):
# 1. 创建对象时候,new方法会被自动调用
print("创建对像,分配空间")
# 2. 为对象分配空间, 返回对象引用
return super().__new__(cls)
def __init__(self):
print("播放器初始化")
player = MusicPlayer()
print(player)

13.2 python 中的单例
- 单例—让类创建的对象,在系统中 只有唯一的一个实例
- 定义一个类属性, 初始值是 None,用于记录 单例对象的引用
- 重写 __new__ 方法
- 如果 类属性 is None,调用父类方法分配空间,并在类属性中记录结果
- 返回 类属性 中记录的 对象引用
class MusicPlayer(object):
# 类属性:记录第一个被创建对像大引用
instance = None
def __new__(cls, *args, **kwargs):
# 1. 判断类属性啥是否为空对像
if cls.instance is None:
# 2. 调用父类大方法,为第一个对像分配空间
cls.instance = super().__new__(cls)
# 3. 返回类属性保存大对象引用
return cls.instance
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)

只执行一次初始化工作
在每次使用 类名() 创建对象时, Python 的解释器都会自动调用两个方法:
- __new__:分配空间
- __init__:对象初始化
虽然对 __new__ 方法改造后,每次都会得到 第一次被创建对象的引用
但是:初始化方法还是会被再次调用!
class MusicPlayer(object):
# 类属性:记录第一个被创建对像大引用
instance = None
def __new__(cls, *args, **kwargs):
# 1. 判断类属性啥是否为空对像
if cls.instance is None:
# 2. 调用父类大方法,为第一个对像分配空间
cls.instance = super().__new__(cls)
# 3. 返回类属性保存大对象引用
return cls.instance
def __init__(self):
print("初始化播放器")
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)

需求
- 让初始化动作 只被执行一次
class MusicPlayer(object):
# 类属性:记录第一个被创建对像大引用
instance = None
init_flag = False
def __new__(cls, *args, **kwargs):
# 1. 判断类属性啥是否为空对像
if cls.instance is None:
# 2. 调用父类大方法,为第一个对像分配空间
cls.instance = super().__new__(cls)
# 3. 返回类属性保存大对象引用
return cls.instance
def __init__(self):
# 1. 判断是否执行初始化动作
if MusicPlayer.init_flag:
return
# 2. 如果没有,在执行初始化动作
print("初始化播放器")
MusicPlayer.init_flag = True
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
14. 异常
14.1 语法
try:
num = int(input("输入整数"))
except:
print("输入正确数字")
14.2 错误类型捕获
完整语法:
try:
pass
except 错误类型1:
pass
except 错误类型2:
pass
except (错误类型3, 错误类型4):
pass
except Exception as result:
print(result)
else:
# 没有异常才会执行的
pass
finally:
print("无论是否有异常都会执行的代码")
例子:
try:
num = int(input("输入:"))
result = 8 / num
print(result)
except ZeroDivisionError:
print("除0错误")
except ValueError:
print("请输入正确整数")
try:
num = int(input("输入:"))
result = 8 / num
print(result)
# except ZeroDivisionError:
# print("除0错误")
except ValueError:
print("请输入正确整数")
except Exception as result:
print("未知错误 %s" % result)
输入:0
未知错误 division by zero
14.3 异常的传递
- 当函数/方法 执行 出现异常,会 将异常传递 给 函数/方法的 调用一方
- 如果 传递到主程序,仍然 没有异常处理,程序才会被终止
提示:
在开发中,可以在主函数中增加 异常捕获
而在主函数中调用的其他函数,只要出现异常,都会传递到主函数的 异常捕获 中
这样就不要在代码中,增加大量的 异常捕获
def demo1():
return int(input("输入:")) def demo2():
return demo1() try:
num = demo2()
result = 8 / num
print(result)
# except ZeroDivisionError:
# print("除0错误")
except ValueError:
print("请输入正确整数")
except Exception as result:
print("未知错误 %s" % result)
else:
print("尝试成功")
finally:
print("无论是否错误都会执行的代码") print("-"*50)
14.4 抛出 raise 异常
创建一个 Exception 对象
使用 raise 关键字 抛出 异常对象
def input_password():
pwd = input("输入密码: ") if len(pwd) >= 8:
return pwd print("主动抛出异常")
# 1. 创建异常对象
ex = Exception("密码长度不够")
# 2. 主动抛出异常
raise ex try:
print(input_password())
except Exception as result:
print(result)
15. 模块
import hm_01_import1 as im01
import hm_01_import2 as im02 im01.say_fuck()
im02.say_hello()
15.1 导入部分工具(可直接使用模块内容)
from...import 导入
两个模块有相同函数,会使用后导入模块的函数
15.2 导入顺序
搜索 当前目录 指定模块名 的文件,如果有就直接导入
如果没有,再搜索 系统目录
- 模块.__file__:可以查看文件位置
15.3 __name__属性
文件被导入时,能够直接执行的代码不需要被执行
hm_09__name__模块.py
def say_hello():
print("小明,hello") if __name__ == "__main__":
print(__name__) print("小明开发的模块")
say_hello()
__main__
小明开发的模块
小明,hello
hm_09__name__测试导入.py
import hm_09__name__模块
print("这是本程序的代码")
hm_09__name__测试导入.py
注意:如果hm_09__name__模块.py 文件不加 if __name__ == "__main__": ,则在hm_09__name__测试导入.py文件中会输出

所以很多Python文件中看到以下格式代码
既可以执行,也可以当做模块导入
# 导入模块
# 定义全局变量
# 定义类
# 定义函数 def main():
# ...
pass if __name__ == '__main__':
main()
16. 包(package)
- 包是一个 包含多个模块的 特殊目录
- 目录下有一个 特殊文件 __init__.py
- 包名的 命名方式 和变量名一致,小写字母+ _
案例演练
1. 新疆一个 dz_message的 包

2. 新建两个Python文件
3. 在外部直接导入 dz_message 的包
__init__.py
要在外界使用包的模块中,需要在 __init__.py 中指定对外界提供的模块列表
from . import send_message
from . import receive_message
导入包的模块
import cn.Douzi.dz_message as dz_message
dz_message.send_message.send("Douzi is Cute")
txt = dz_message.receive_message.receive()
print(txt)

17. 制作发布压缩包
17.1 创建setup.py
from distutils.core import setup setup()
setup(name="hm_message", # 包名
version="1.0",
description="Douzi's 发送和接受消息模块",
long_description="完整的发送和接受消息模块", # 完整描述信息
author="Douzi", # 作者
url="www.cnblogs.com/douzujun/", # 主页
py_modules=["dz_message.send_message",
"dz_message.receive_message"])
17.2 构建模块
python3 setup.py build
17.3 生成发布压缩包
python3 setup.py sdist
18. 安装模块

sudo python3 setup.py install

Python复习笔记(五)面向对象的更多相关文章
- Python进阶(十五)----面向对象之~继承(单继承,多继承MRO算法)
Python进阶(十五)----面向对象之~继承 一丶面向对象的三大特性:封装,继承,多态 二丶什么是继承 # 什么是继承 # b 继承 a ,b是a的子类 派生类 , a是b的超类 基类 父类 # ...
- python学习笔记六 面向对象相关下(基础篇)
面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以将多函数中公用的变量封装到对象中) 对象,根据模板创建的 ...
- Python复习笔记(四)高阶函数/返回函数/匿名函数/偏函数/装饰器
一.map/reduce map map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次 作用到序列的每个元素,并把结果作为新的Iterator返回. reduce r ...
- python学习笔记(10):面向对象
一.类和实例 1.类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例. 2.对象:通过类定义的数据结构实例.对象包括两个数据成员( ...
- python学习笔记(7): 面向对象
class Foo: #类中的函数 def bar(self): #功能阐述 print('Bar') pass def hello(self,name): print('i am %s' %name ...
- python 学习笔记7 面向对象编程
一.概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." ...
- Python学习笔记五
一. 递归 递归函数: def a (): print ("from b") b() def b(): print("from a ") a() a() 递推和 ...
- python学习笔记(五)
面向对象方法 元组的二义性:不明确参数代表的含义 circle=(2,4,6) def distance_from_origin(x,y): return "返回x,y坐标" de ...
- python学习笔记_week6_面向对象
面向对象 介绍(特性(class.object--->封装.继承,多态)).--->世界万物,皆可分类:世界万物,皆可对象 只要是对象,就肯定属于某种品类:只要是对象,就肯定有属性 你是上 ...
随机推荐
- studio 连不上远程仓库的各种原因分析
Unable to open the project 1.远程服务器挂了2.网络断了3.登录远程服务器的账号.密码错了4.远程仓库的url地址,被本地的hosts文件重定向了5.要下载远程仓库的某个j ...
- Codeforces Round #463 F. Escape Through Leaf (李超线段树合并)
听说正解是啥 set启发式合并+维护凸包+二分 根本不会啊 , 只会 李超线段树合并 啦 ... 题意 给你一颗有 \(n\) 个点的树 , 每个节点有两个权值 \(a_i, b_i\) . 从 \( ...
- ftp利用脚本添加本地用户
指定用户名,家目录,密码,顺序不可颠倒.eg: sh 脚本名 用户名 家目录 密码 #!/bin/bash # set -e ] //判断给定参数是否为三个 homepath=$ password=$ ...
- 【BZOJ3653】谈笑风生(长链剖分)
[BZOJ3653]谈笑风生(长链剖分) 题面 BZOJ 洛谷 权限题啊.... 题解 首先根据题目给的条件,发现\(a,b\)都要是\(c\)的父亲. 所以这三个点是树上的一条深度单增的链. 因为\ ...
- 【CF671D】Roads in Yusland(贪心,左偏树)
[CF671D]Roads in Yusland(贪心,左偏树) 题面 洛谷 CF 题解 无解的情况随便怎么搞搞提前处理掉. 通过严密(大雾)地推导后,发现问题可以转化成这个问题: 给定一棵树,每条边 ...
- Linux网络基础-总
目录 Linux网络基础 一.网卡和数据包的转发 1.收包流程 二.多网卡bonding 三.SR-IOV 四.DPDK 五.TUN/TAP 六.Linux bridge 和VLAN 七.TCP/IP ...
- A.01.02—模块的输入—高端输入
高端输入即一个高电平信号输入到模块,模块采样时最典型的是采用下拉电阻采样,当然,还有限流电阻和分压电阻,具体可以参见实际电路. 高端输入在汽车上用得不多,这种类型的输入既可以是开关提供的也可以是模块提 ...
- LVS搭建负载均衡(二)DR模型
应用场景:LVS配置负载均衡方式之一:dr 测试环境: 配置步骤: 1. 在主机lvs上安装ipvsadm ~]# yum install ipvsadm -y ~]# ipvsadm //启动:该命 ...
- golang go语言通道类型的通道示例 通道的通道
几点注意:go的无缓存通道 通道make 创建后,即使里面是空的,也可以取里面内容.但是程序会被阻塞. 通道的规则是没人取,是不能往里面放的.放的线程会阻塞. 最外层的requestChan相当于一个 ...
- 【SPOJ10707】COT2 - Count on a tree II
题目大意:给定一棵 N 个节点的无根树,每个节点有一个颜色.现有 M 个询问,每次询问一条树链上的不同颜色数. 题解:学会了树上莫队. 树上莫队是将节点按照欧拉序进行排序,将树上问题转化成序列上的问题 ...