python和对象复习_Python复习笔记(五)面向对象

1. __init__方法

#1. 为对象在内存 中分配空间 -- 创建对象#2. 为对象属性 设置初始值 -- 初始化方法(init)+--------------#3. __init__: 专门用来定义一个类 具有哪些属性的方法!

classCat:def __init__(self):#self.属性名 = 属性的初始值

self.name = "TOM"

#print("这是一个初始化方法")

defeat(self):print("%s 吃鱼" %self.name)#使用类名()创建对象的时候会自动调用初始化方法__init__

tom =Cat()print(tom.name)

TOM 我去了

TOM

2. 利用参数设置属性初始值

#1. 为对象在内存 中分配空间 -- 创建对象#2. 为对象属性 设置初始值 -- 初始化方法(init)#3. __init__: 专门用来定义一个类 具有哪些属性的方法!

classCat:def __init__(self, new_name):#self.属性名 = 属性的初始值

self.name =new_name#print("这是一个初始化方法")

defeat(self):print("%s 吃鱼" %self.name)#使用类名()创建对象的时候会自动调用初始化方法__init__

tom = Cat("TOM")print(tom.name)

lazy_Cat= Cat("Lazy")

lazy_Cat.eat()

3. __del__方法

classCat:def __init__(self, new_name):#self.属性名 = 属性的初始值+

self.name =new_nameprint("%s 我来了" %self.name)defeat(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"""

classCat:def __init__(self, new_name):#self.属性名 = 属性的初始值+

self.name =new_nameprint("%s 我来了" %self.name)defeat(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

classWomen:def __init__(self, name):

self.name=name

self.__age = 18

def __secret(self):print("%s 的年龄是 %d" % (self.name, self.__age))defsay(self):

self.__secret()

xiaofang= Women("小芳")#私有属性不能被直接访问#print(xiaofang.age)

#在对象的方法内部可以访问#私有方法同样不可以在外界方法#xiaofang.__secret()

xiaofang.say()

7. 伪私有属性和私有方法(不推荐使用)

classWomen:def __init__(self, name):

self.name=name

self.__age = 18

def __secret(self):print("%s 的年龄是 %d" % (self.name, self.__age))defsay(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"""

classAnimal:defeat(self):print("吃")defdrink(self):print("喝")defrun(self):print("跑")defsleep(self):print("睡")classDog(Animal):defbark(self):print("www")classXiaoTianQuan(Dog):deffly(self):print("飞")defbark(self):print("叫的跟神一样")#使用super(). 调用原本在父类中封装的方法

super().bark()#父类名.方法(self). 调用父类中封装方法

Dog.bark(self)

dog=Dog()

dog.eat()

xiaotian=XiaoTianQuan()

xiaotian.bark()

叫的跟神一样

www

www

注意:

子类对象 不能 在自己方法内部 直接 访问父类的私有属性或私有方法(可以通过父类公共方法访问)

子类对象 在外界可以访问到父类的公有属性和方法

8.2 多继承

概念:子类可以拥有多个父类,并且具有 所有父类 的属性和方法

classA:deftest(self):print("A class")classB:defdemo(self):print("B demo")classC(A, B):passc=C()

c.test()

c.demo()

注意:父类存在同名属性和方法,少用多继承

python中的MRO——方法搜索顺序:主要用于 在多继承时判断方法, 属性 的调用路径

python中针对 类 提供一个 内置属性 __mro__ 可以查看方法搜索顺序

classA:deftest(self):print("A class")defdemo(self):print("A Demo")classB:deftest(self):print("B test")defdemo(self):print("B demo")classC(B, A):passc=C()

c.test()

c.demo()#确定C类方法调用顺序

print(C.__mro__)

8.3 推荐使用新式类 class A(object):

9. 多态

9.1 调用相同的父类方法,产生不同的执行结果

多态可以 增加代码的 灵活度

以 继承 和 重写父类方法为前提

是调用方法的 技巧,不会影响类的内部设计

classDog(object):def __init__(self, name):

self.name=namedefgame(self):print("%s 玩耍..." %self.name)classXiaoTianDog(Dog):defgame(self):print("%s 飞到天上玩耍..." %self.name)classPerson(object):def __init__(self, name):

self.name=namedefgame_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. 对象.类属性(不推荐)

classTool(object):#使用赋值语句定义 类属性,记录所有工具对象大数量

count =0def __init__(self, name):

self.name=name

Tool.count+= 1tool1= Tool("斧子")

tool1= Tool("水桶")print(Tool.count)

2

12. 类方法

类方法 就是针对 类对象定义的方法

在 类方法内部 可以直接访问 类属性或者调用其他的 类方法

语法如下;

@classmethoddef类方法名(cls):pass

修饰器 @classmethod 来标识,告诉解释器 这是一个类方法

类方法 第一个参数 应该是 cls

由 哪一个类 调用的方法,方法内的 cls就是 哪一个类的引用

这个参数 和实例方法 的 第一参数 是 self 类似

提示 使用其他名称也可以,不过习惯使用 cls

通过 类名。调用 类方法,调用方法时,不需要传递 cls 参数

在方法内部:

可以通过 cls,访问 类的属性

也可以通过cls,调用 其他类方法

classTool(object):#使用赋值语句定义 类属性,记录所有工具对象大数量

count =0

@classmethoddefshow_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()

综合

classTool(object):#使用赋值语句定义 类属性,记录所有工具对象大数量

count =0

@classmethoddefshow_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 参数

classMusicPlayer(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,调用父类方法分配空间,并在类属性中记录结果

返回 类属性中记录的 对象引用

classMusicPlayer(object):#类属性:记录第一个被创建对像大引用

instance =Nonedef __new__(cls, *args, **kwargs):#1. 判断类属性啥是否为空对像

if cls.instance isNone:#2. 调用父类大方法,为第一个对像分配空间

cls.instance = super().__new__(cls)#3. 返回类属性保存大对象引用

returncls.instance

player1=MusicPlayer()print(player1)

player2=MusicPlayer()print(player2)

只执行一次初始化工作

在每次使用 类名() 创建对象时, Python 的解释器都会自动调用两个方法:

__new__:分配空间

__init__:对象初始化

虽然对 __new__ 方法改造后,每次都会得到 第一次被创建对象的引用

但是:初始化方法还是会被再次调用!

classMusicPlayer(object):#类属性:记录第一个被创建对像大引用

instance =Nonedef __new__(cls, *args, **kwargs):#1. 判断类属性啥是否为空对像

if cls.instance isNone:#2. 调用父类大方法,为第一个对像分配空间

cls.instance = super().__new__(cls)#3. 返回类属性保存大对象引用

returncls.instancedef __init__(self):print("初始化播放器")

player1=MusicPlayer()print(player1)

player2=MusicPlayer()print(player2)

需求

让初始化动作 只被执行一次

classMusicPlayer(object):#类属性:记录第一个被创建对像大引用

instance =None

init_flag=Falsedef __new__(cls, *args, **kwargs):#1. 判断类属性啥是否为空对像

if cls.instance isNone:#2. 调用父类大方法,为第一个对像分配空间

cls.instance = super().__new__(cls)#3. 返回类属性保存大对象引用

returncls.instancedef __init__(self):#1. 判断是否执行初始化动作

ifMusicPlayer.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

exceptException as result:print(result)else:#没有异常才会执行的

pass

finally:print("无论是否有异常都会执行的代码")

例子:

try:

num= int(input("输入:"))

result= 8 /numprint(result)exceptZeroDivisionError:print("除0错误")exceptValueError:print("请输入正确整数")

try:

num= int(input("输入:"))

result= 8 /numprint(result)#except ZeroDivisionError:#print("除0错误")

exceptValueError:print("请输入正确整数")exceptException as result:print("未知错误 %s" % result)

输入:0

未知错误 division by zero

14.3 异常的传递

当函数/方法 执行 出现异常,会 将异常传递给 函数/方法的 调用一方

如果 传递到主程序,仍然 没有异常处理,程序才会被终止

提示:

在开发中,可以在主函数中增加 异常捕获

而在主函数中调用的其他函数,只要出现异常,都会传递到主函数的 异常捕获中

这样就不要在代码中,增加大量的 异常捕获

defdemo1():return int(input("输入:"))defdemo2():returndemo1()try:

num=demo2()

result= 8 /numprint(result)#except ZeroDivisionError:#print("除0错误")

exceptValueError:print("请输入正确整数")exceptException as result:print("未知错误 %s" %result)else:print("尝试成功")finally:print("无论是否错误都会执行的代码")print("-"*50)

14.4 抛出 raise 异常

创建一个 Exception 对象

使用 raise 关键字 抛出 异常对象

definput_password():

pwd= input("输入密码:")if len(pwd) >= 8:returnpwdprint("主动抛出异常")#1. 创建异常对象

ex = Exception("密码长度不够")#2. 主动抛出异常

raiseextry:print(input_password())exceptException as result:print(result)

15. 模块

importhm_01_import1 as im01importhm_01_import2 as im02

im01.say_fuck()

im02.say_hello()

15.1 导入部分工具(可直接使用模块内容)

from...import 导入

两个模块有相同函数,会使用后导入模块的函数

15.2 导入顺序

搜索 当前目录 指定模块名的文件,如果有就直接导入

如果没有,再搜索 系统目录

模块.__file__:可以查看文件位置

15.3 __name__属性

文件被导入时,能够直接执行的代码不需要被执行

hm_09__name__模块.py

defsay_hello():print("小明,hello")if __name__ == "__main__":print(__name__)print("小明开发的模块")

say_hello()

__main__

小明开发的模块

小明,hello

hm_09__name__测试导入.py

importhm_09__name__模块print("这是本程序的代码")

hm_09__name__测试导入.py

注意:如果hm_09__name__模块.py 文件不加 if __name__ == "__main__": ,则在hm_09__name__测试导入.py文件中会输出

所以很多Python文件中看到以下格式代码

既可以执行,也可以当做模块导入

#导入模块#定义全局变量#定义类#定义函数

defmain():#...

pass

if __name__ == '__main__':

main()

16. 包(package)

包是一个 包含多个模块的 特殊目录

目录下有一个 特殊文件__init__.py

包名的 命名方式和变量名一致,小写字母+ _

案例演练

1. 新疆一个 dz_message的 包

2. 新建两个Python文件

3. 在外部直接导入 dz_message 的包

__init__.py

要在外界使用包的模块中,需要在 __init__.py 中指定对外界提供的模块列表

from . importsend_messagefrom . import receive_message

导入包的模块

importcn.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 importsetup

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值