Python 基础之面向对象之常用魔术方法
一.__init__魔术属性
触发时机:实例化对象,初始化的时候触发
功能:为对象添加成员,用来做初始化的
参数:参数不固定,至少一个self参数
返回值:无
1.基本用法
#例:
class MyClass():
def __init__(self):
#print(111)
self.name = "one"
#实例化对象 [类的实例化]
obj = MyClass()
print(obj.name)
2.__init__可以传递多个参数
#例:
class MyClass():
def __init__(self,name):
#self.name 这个name是成员输出name
#self.name = name 后面的name是传进来的参数
self.name = name
#类的实例化 实例化对象
#把参数传递到MyClass 后面的这个括号里
obj = MyClass("TWO")
print(obj.name)
3.综合案例
类可以是一个,但对象可以是多个,对象之间彼此独立
#例:
class Children():
def __init__(self,name,eyes_color):
self.name = name
self.eyes_color = eyes_color
def eat(self):
print("小孩子生下来的时候,饿了就会吃东西")
def drink(self):
print("小孩子生下来的时候,渴了就会喝东西")
def smile(self):
print("小孩在只要不饿不渴就会经常笑")
def obj_info(self):
print("小孩的姓名:{},小孩的眼睛的颜色:{}".format(self.name,self.eyes_color))
'''
同一个类产生三个对象,但是每个对象彼此都是堵路的
而且都可以调用类中的公有成员属性方法
'''
child1 = Children("ONE","blue")
child1.obj_info()
child1.eat()
print("====================")
child2 = Children("two","blown")
child2.obj_info()
child2.smile()
print("3======================")
child3 = Children('three','red')
child3.obj_info()
child3.drink()
二.__new__
触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
#自己理解:只要有实例化那个类,类里面的new
功能:控制对象的创建过程
参数:至少一个cls接受当前的类,其他根据情况决定
返回值:通常返回对象或None
1.基本用法
python3.x 新式类 python2.x 旧式类,新式类不需要每次都写一次object,默认继承
作用:控制创建的对象
#例:
class MyClass2():
abc = 1
obj2 = MyClass2()
class MyClass(object):
def __new__(cls):
print(cls) #<class '__main__.MyClass'>
#借助object父类方法里面__new__来为本类创建一个对象
#return object.__new__(cls) #返回一个本类对象
#return None #返回一个空对象
return obj2 #返回的是一个其他类的对象
# pass
#实例化对象obj
obj = MyClass()
print(obj)
print(obj2.abc)
2.对比__new__和__init__的触发时机
__new__ 魔术方法是用来创建对象的
__init__ 魔术方法是用来初始化对象的
得现有对象,才能初始化,没有对象初始化谁?
__new__的触发时机要快于__init__
__new__ __init__ 这两个方法的参数要一一匹配
(1)一个参数
#例:
class Boat():
def __new__(cls,name):
print(1)
return object.__new__(cls)
def __init__(self,name):
self.name = name
obj = Boat("大锤")
(2)无限个参数
#例:
class Boat():
def __new__(cls, *args, **kwargs):
print(1)
return object.__new__(cls)
def __init__(self,*args, **kwargs):
strvar = ""
for i in args:
strvar += i + " "
print("小船的贡献值有: ",strvar)
print("小船的名字是:",format(kwargs['name']))
obj = Boat("one", "two", "three", "four", name="five")
#运行结果:
1
小船的贡献值有: one two three four
小船的名字是: five
#因为调用了Boat即触发new 和 init魔术属性,init对类进行初始化
(3)如果通过__new__返回的是其他类的对象,不会触发自己本类的__init__
#因为__init__初始化的是本类对象
#例:
class MyClass2():
abc = 3
obj2 = MyClass2()
class Boat():
def __new__(cls,*args,**kwargs):
return obj2 #返回的是最上面的obj2
def __init__(self):
print("init调用了")
obj = Boat()
print(obj.abc)
#运行结果为:
3
#因为__new__在__init__创建之前调用,而new里调用的是MyClass的对象,所有输出3,而并没有调用本类的对象,__new__返回的是其他类的对象,不会触发自己本类的__init__
3.单态模式(单例模式)
无论实例化多少次,都有且只有一个对象
最终目的:为了节省内存空间,应用的场景是只调用相关的成员属性或方法,而不用动态添加成员属性方法的环境中'''
__obj 变成私有,控制不让用户在类外直接获取obj,而是用__new__来控制返回的逻辑
先判断cls.__obj 是不是None
如果是None,代表是一个空的对象,那么就利用父类的__new__方法来创建对象
如果不是一个空对象,代表先前早已实例化过一个对象
就把这个对象给他返回
(1)基本用法
class Singleton():
__obj = None
def __new__(cls, *args, **kwargs):
if cls.__obj is None:
#借助父类创建对象
obj = object.__new__(cls)
#把这个对象复制给类中成员属性__obj
cls.__obj = obj
return cls.__obj
#第一次创建时,因为cls.__obj 是None 所有创建一个对象
obj = Singleton()
print(obj)
#第二次实例化时,因为cls.__obj 不是None,直接返回上一次创建的那个对象
obj = Singleton()
print(obj)
# 第三次实例化时,同第二次
obj = Singleton()
print(obj)
obj = Singleton()
print(obj)
(2)改造
class Singleton():
__obj = None
def __new__(cls, *args, **kwargs):
if cls.__obj is None:
cls.__obj = object.__new__(cls)
return cls.__obj
def __init__(self,name):
self.name = name
obj1 = Singleton("one")
obj2 = Singleton("two")
print(obj1.name)
print(obj2.name)
#解析:
第一次是创建对象,并且通过init初始化对象,为该对象赋值成员属性name
self.name = one
第二次是直接返回上一次对象,然后对他进行初始化,为该对象赋值成员属性name
self.name = two
两个不同的变量名指向的是同一个对象
而此时该对象的成员属性name 这个值是two
print(obj1.name)
print(obj2.name)
打印的都是two
三.__del__ 析构方法 __init__ 构造方法
触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
功能:对象使用完毕后资源回收
参数:一个self接受对象
返回值:无
#例:
class Dog():
def __init__(self,name):
self.name = name
def eat(self,something):
print("可爱的小狗{},喜欢吃{}".format(self.name,something))
def __del__(self):
print("__del__方法被触发")
1.页面执行完毕回收所有变量
obj = Dog("Lwhite")
obj.eat("bone")
print("=======")
2.所有对象被del的时候
#只有当所有指向该变量都删除的时候,才算删除单位对象
obj2 = obj
print("=========start=============")
del obj
del obj2
print("=============end==============")
3.用类来模拟文件读和写的操作
#例1:例1使用的是文件操作的方法
# fp = open("ceshi222.txt",mode="w",encoding="utf-8")
# fp.write("ewqeqwqewqqeqeq")
# fp.close()
#
# fp = open("ceshi222.txt",mode="r",encoding="utf-8")
# res = fp.read()
# fp.close()
# print(res)
print("=================")
#例2:例2是用类来模拟文件的读的操作
import os
class MyFile():
#判断是否创建MyFile该对象
def __new__(cls, filename):
if os.path.exists(filename):
return object.__new__(cls)
return print("该文件不存在")
#产生文件对象
def __init__(self,filename):
self.fp = open(filename,mode="r",encoding="utf-8")
#读取文件
def readfile(self):
res = self.fp.read()
return res
def __del__(self):
print(0)
#自动触发__del__,帮助我们关闭文件
self.fp.close()
obj = MyFile("ceshi222.txt")
res = obj.readfile()
print(res)
#例3是用来模拟文件读和写的操作
#以下代码的功能是将内容写入到一个文件中在读取这个文件中的内容
#例:
import os
class MyFile():
#产生文件对象
def __init__(self,filename):
self.filename = filename
self.fp = open(filename,mode="w+",encoding="utf-8")
#写入文件
def writefile(self,content):
self.fp.write(content)
#读取文件
def readfile(self):
#self.fp = open(self.filename, mode="r+", encoding="utf-8")
self.fp.seek(0)
res = self.fp.read()
#print(res)
return res
def __del__(self):
#print(0)
#自动触发__del__,帮助我们关闭文件
self.fp.close()
file_name = input("请输入您写入的文件名:")
obj = MyFile(file_name)
content = input("请输入您要输入的内容:")
obj.writefile(content)
res = obj.readfile()
print(res)
#例3的效果是,让你输入内容的文件名,如果这个文件名存在,继续输入内容,如果不存在会自动创建一个并
让其输入内容,输入后返回输出输入的内容结果,也可以在文件中进行查看,内容已经写到文件中.
四.__call__ 魔术方法
触发时机: 把对象当作函数调用的时候自动触发
功能:模拟函数化操作
参数:参数不固定,至少一个self参数
返回值:看需求
1.基本语法
class MyClass():
def __call__(self):
print("__call方法被调用了")
return "done"
obj = MyClass()
res = obj()
print(res)
2.模拟洗衣服的过程
class Wash():
#使用call方法,进行统一的调用
def __call__(self,something):
self.something = something
print("以下是洗{}的过程:".format(something))
self.step1()
self.step2()
self.step3()
def step1(self):
print("第一步,把{}放到洗衣机里".format(self.something))
def step2(self):
print("第二步,倒入洗衣液,开启洗衣机")
def step3(self):
print("第三步,将洗好的衣服晾上去晒干")
obj = Wash()
#面向客户的代码形式
# obj.step1()
# # obj.step2()
# # obj.step3()
#call 魔术用法
obj("袜子")
3.模拟内置int方法实现myint
#例:
import math
class MyInt():
def stoi(self,n,sign=1):
res = n.lstrip("0")
if res == "":
return 0
num = eval(res) * sign #eval 将字符串当代码运行
return num
def __call__(self,n):
#判断的是布尔类型
if isinstance(n,bool):
if n == True:
return 1
else:
return 0
#判断的是整型
elif isinstance(n,int):
return n
#判断的是浮点型
elif isinstance(n,float):
if n < 0:
return math.ceil(n)
else:
return math.floor(n)
#判断的是字符串
elif isinstance(n,str):
if (n[0] == "-" or n[0] == "+") and n[1:].isdecimal():
if n[0] == "+":
sign = 1
else:
sign = -1
return self.stoi(n[1:],sign)
elif n.isdecimal():
#如果能够走到这个条件,一定没有带任何正负号
return self.stoi(n)
else:
return "对不起,老弟,这个算不了"
else:
print("对不起,老哥,这个算不了")
myint = MyInt()
res = myint(False)
print(res)
res = myint(5)
print(res)
res = myint(-5.5)
print(res)
res = myint(-000000000)
print(res)
res = myint("00000123456")
print(res)
res = myint("-231312")
print(res)
res = int(5+6)
print(res)
res = myint(0b11)
print(res)
五.__str__
触发时机:使用print(对象)或str(对象)的时候触发
功能:查看对象
参数:一个self接受当前对象
返回值:必须返回字符串类型
#例:
class Cat():
gift = "抓老鼠"
def __init__(self,name):
self.name = name
def cat_info(self):
strvar = "这个对象的名字{},这个对象的天赋:{}".format(self.name,self.gift)
return strvar
def __str__(self):
return self.cat_info()
tom = Cat("汤姆")
#(1)打印对象触发__str__方法
#print(tom)
#(2)str 强转对象时候触发__str__方法
res = str(tom)
print(res)
六.__repr__
触发时机:使用repr(对象)的时候触发
功能:查看对象,与魔术方法__str__相似
参数:一个self接受当前对象
返回值:必须返回字符串类型
#例:
class Mouse():
gift = "打洞"
def __init__(self,name):
self.name = name
def mouse_info(self):
strvar = "该对象的名字{},它的天赋是{},龙生龙,凤生凤,老鼠的儿子会打洞".format(self.name,self.gift)
return strvar
def __repr__(self):
return self.mouse_info()
#在系统的底层加了如下一句话:如果存在__repr__这个方法,就把它赋值给__str__
#__str__ = __repr__
jerry = Mouse("杰瑞")
#res = repr(jerry)
#print(res)
print(jerry)
七.__bool__ 魔术方法
触发时机:使用bool (对象)的时候自动触发
功能:强转对象
参数:一个self接受当前对象
返回值:必须是布尔类型
类似的还有如下等等(了解):
__complex__ 被complex强转对象时调用
__int__(self) 被int强转对象时调用
__float__(self) 被float强转对象时调用
...
...
#例:
class MyBool():
def __bool__(self):
print(222)
#return True
return False
obj = MyBool()
res = bool(obj)
print(res)
八.__add__魔术方法 (与之相关的 __radd__ 反向加法)
触发时机: 使用对象进行运算相加的时候自动触发
功能:对象运算
参数:二个对象参数
返回值:运算后的值
类似的还有如下等等(了解):
__sub__(self,other) 定义减法的行为: -
__mul__(self,other) 定义乘法的行为:
__truediv__(self,other) 定义真除法的行为: /
...
...
#例1:
class Myadd():
def __init__(self,num):
self.num = num
#对象+数值,并且对象在+加号的左边,自动触发__add__方法
def __add__(self,other):
#self.num => 3 + 56 => 59
return self.num + other
def __radd__(self, other):
#self 接收b ,other 接收 33
return self.num + other * 10
#1.当对象在加号的右侧 自动触发add方法
a = Myadd(5)
res = a + 56
print(res)
#2.当对象在加号的右侧 自动触发radd方法
b = Myadd(5)
res = 33 + b
print(res)
##代码解析:
有点像:
a + b = ?
res = a+b
print(res)
#代码步骤解析
a在几号的左侧,触发add魔术方法
self.num + other => 3 + b
b在加号的右侧,触发add魔术方法
res = 3 + b
self.num + other * 10 => 5 + 3*10 => 35
九. __len__ 魔术方法
触发时机:使用len(对象)的时候自动触发
功能:用于检测对象中或者类中某个内容的个数
参数:一个self接收当前对象
返回值:必须返回整型
#用len(对象)方式,算出该对象所归属的类有多少自定义成员
#例:
class MyLen():
pty1 = 1
pty2 = 2
__pty3 = 3
def func1(self):
pass
def func2(self):
pass
def func3(self):
pass
def func4(self):
pass
def __len__(self):
#print(MyLen.__dict__)
dic = MyLen.__dict__
#print(dic)
lst = [i for i in dic if not( i.startswith("__") and i.endswith("__")) ]
num = len(lst)
return num
obj = MyLen()
res = len(obj)
print(res)
"""
这个是 MyLen.__dict__里面的内容:
{'__module__': '__main__',
'pty1': 1, 'pty2': 2,
'_MyLen__pty3': 3,
'func1': <function MyLen.func1 at 0x00000281A9871950>,
'func2': <function MyLen.func2 at 0x00000281A98719D8>,
'func3': <function MyLen.func3 at 0x00000281A9871A60>,
'func4': <function MyLen.func4 at 0x00000281A9871AE8>,
'__len__': <function MyLen.__len__ at 0x00000281A9871B70>,
'__dict__': <attribute '__dict__' of 'MyLen' objects>,
'__weakref__': <attribute '__weakref__' of 'MyLen' objects>,
'__doc__': None}
"""
Python 基础之面向对象之常用魔术方法的更多相关文章
- Python 基础之面向对象之类中的方法和与类相关的魔术属性以及反射
一.类中的方法 普通方法: 没有参数,只能类调用绑定方法: (1)绑定到对象(自动传递对象参数) (2)绑定到类(自动传递参数)静态方法: 无论是类还是对象,都能调用的方法#例:class Dog() ...
- python常用魔术方法概览
构造和初始化 __init__(self, args) 构造函数 __new__(cls) 传入的是类实例 __del__(self) 析构函数,调用 del cls 时会被调用 属性访问控制 __g ...
- Python 基础 四 面向对象杂谈
Python 基础 四 面向对象杂谈 一.isinstance(obj,cls) 与issubcalss(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls ...
- Python基础------列表,元组的调用方法
Python基础------列表,元组的调用方法@@@ 一. 列表 Python中的列表和歌曲列表类似,也是由一系列的按特定顺序排列的元素组成的,在内容上,可以将整数,实数,字符串,列表,元组等任何类 ...
- 自学Python之路-Python基础+模块+面向对象+函数
自学Python之路-Python基础+模块+面向对象+函数 自学Python之路[第一回]:初识Python 1.1 自学Python1.1-简介 1.2 自学Python1.2-环境的 ...
- 二十. Python基础(20)--面向对象的基础
二十. Python基础(20)--面向对象的基础 1 ● 类/对象/实例化 类:具有相同属性.和方法的一类人/事/物 对象(实例): 具体的某一个人/事/物 实例化: 用类创建对象的过程→类名(参数 ...
- python基础,函数,面向对象,模块练习
---恢复内容开始--- python基础,函数,面向对象,模块练习 1,简述python中基本数据类型中表示False的数据有哪些? # [] {} () None 0 2,位和字节的关系? # ...
- (转)Python成长之路【第九篇】:Python基础之面向对象
一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...
- php中的常用魔术方法总结
以下是对php中的常用魔术方法进行了详细的总结介绍,需要的朋友可以过来参考下 常用的魔术方法有:__Tostring () __Call() __autoLoad() __ clone() __GET ...
随机推荐
- 【代码学习】PYTHON 生成器
一.生成器 一遍循环一遍计算的机制,称为生成器 二.生成器的特点: 1.节约内存 2.迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的, ...
- Bug搬运工-CSCvf74866:Webauth scaling improvements - fix problem with GUI going unresponsive with HTTPS redirect
Webauth scaling improvements - fix problem with GUI going unresponsive with HTTPS redirect CSCvf7486 ...
- 【C语言】输入一个年份和月份,输出该月的天数
分析: 三种类型, A.2月比较特殊,平年的2月只有28天,而闰年的2月有 29 天: B.4.6.9.11月: C.其他1.3.5.7.8.10.12月. 代码: /*输入一个年份和月份,输出该月的 ...
- 5种JVM调优配置方法概览!!!
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- MySQL 将字符串转换为数字
转载自:https://www.cnblogs.com/xiaoleiel/p/8316508.html 在操作mysql时,经常需要将字符转换成数字,这一步虽然简单,但不常用的话也很容易忘记,现将在 ...
- python的空格和tab混用报错问题
python中的空格和tab键不能混用,如果则会报类似如下的错误: IndentationError: unindent does not match any outer indentation le ...
- docker部署-windows环境
docker部署-windows环境 1. docker windows 1.1. 安装 win7或者win8需要利用docker toolbox来安装,其是一个docker工具集,w ...
- Linux下运行SuperSocket记录
Linux下运行SuperSocket程序步骤 需要将原程序的配置文件中的内容拷贝一份,改名成SuperSocket.SocketService.exe.config1.Linux中运行.Net程 ...
- Jmeter 如何发起一个post请求
举例平台:https://www.juhe.cn/docs/api/id/65 前提条件: 1)要在聚合网站注册实名认证才可以收到Key,用于Get请求的参数数值 2)Jmeter本地安装好 3.这是 ...
- 【PAT甲级】1042 Shuffling Machine (20 分)
题意: 输入洗牌次数K(<=20),输入54张牌每次洗入的位置(不是交换的位置),输出洗好的牌. AAAAAccepted code: #define HAVE_STRUCT_TIMESPEC ...