### __init__魔术方法
#__init__魔术方法(构造方法)只要父类或者子类中有init 必须在实例化对象的时候给与初始化参数,否则报错★★★★★,
#如果init中给出self外其他参数,就可以直接在类内调用,如果没有,就用传进来的参数
#除了self本身,有几个参数要传几个参数,一一对应
'''
触发时机:实例化类生成对象,初始化的时候触发
功能:为对象添加成员
参数:参数不固定,至少一个self参数
返回值:无
'''
(1) 基本语法
class MyClass():
def __init__(self):
print(11)
self.name = "张婕"
print(22)
实例化对象
print(33)
obj = MyClass()
print(44)
print(obj.name)
print(55)
(2) 带有多个参数的构造方法
class MyClass():
def __init__(self,name):
# 对象.成员属性(自定义) = 参数值
self.name = name
实例化 (如果构造方法里面含有额外参数,在实例化时,需要传参)
obj = MyClass("刘")
print(obj.name)
(3) 类可以是1个,对象可以是多个,可以通过一个类实例化多个不同的对象
"""每创建一个对象,都会单独占用一个空间,创建的越多,占用的空间就越大"""
class Children():
def __init__(self,name,skin):
self.name = name
self.skin = skin
def cry(self):
print("小孩下生直接哭~")
def drink(self):
print("小孩下生直接吸奶奶~")
def __eat(self):
print("小孩自己吃自己的手指")
def pub_func(self):
print("该对象的名字是{},该对象的肤色是{}".format(self.name,self.skin))
# 注意点
def pub_func2(self,name,skin):
print("该对象的名字是{},该对象的肤色是{}".format(name,skin))
不能直接写name,要用self调用才可以
创建第一个对象
afanda = Children("王铁锤","蓝色")
afanda.cry()
afanda.pub_func()
创建第二个对象
dan = Children("王钢蛋","黑色")
dan.drink()
dan.pub_func()
### new 魔术方法
#一般用于单态时才会用new★★★★★
#要借助父类object 类.方法() 才能创建一个全新的本类对象 例如;obj = object.__new__(cls)
#通过new可以返回不同的对象.可以是自己的 ,可以是其他人的,也可以不返回
#返回自己的对象,要借助父类的new才可以实现
'''
触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
功能:控制对象的创建过程
参数:至少一个cls接受当前的类,其他根据情况决定
返回值:通常返回对象或None
'''
(1) 基本语法
class MyClass():
a = 1
obj = MyClass()
print(obj)
class MyClass1(object):
def __new__(cls):
print(cls)
# (1)借助父类object 类.方法()
# obj = object.__new__(cls)
# 返回本类自己的对象
# return obj
# (2)返回其他类的对象
# return obj
# (3)不返回任何对象
return None
obj = MyClass1()
print(obj)
print(obj.a)
(2) new方法的触发时机要快于init
"""
__new__ 用来创建对象,创建本类对象要借助父类new
__init__ 用来初始化对象(前提的有对象)
先创建对象,再去初始化对象,所以new快于init
"""
class Boat():
def __init__(self):
print(2)
def __new__(cls):
print(1)
return object.__new__(cls)
obj = Boat()
(3) new方法的参数要和init方法参数一一对象
一个参数
class Boat():
def __new__(cls,name):
return object.__new__(cls)
def __init__(self,name):
self.name = name
obj = Boat("泰坦尼克号")
print(obj.name)
多个参数
class Boat():
def __new__(cls,*args,**kwargs):
return object.__new__(cls)
def __init__(self,name,a,b,c,d,e):
self.name = name
obj = Boat("泰坦尼克号",2,3,4,5,6)
print(obj.name)
(4) 注意点
"""如果返回的不是本类的对象,不会触发__init__构造方法"""
class MyClass():
a = 1
other_obj = MyClass()
class Boat():
def __new__(cls):
return other_obj
def __init__(self):
print("构造方法被触发~")
obj = Boat()
单态(例)模式 : 无论实例化多少次,都有且只有一个对象
"""
目的意义:
为了节省内存空间,仅仅是为了调用类中的成员,
不需要额外给该对象添加任何成员,这个场景,使用单态.
比如:操作数据库的增删改查这样的类,是不需要的.
"""
(1) 基本语法
class Singleton():
__obj = None★★★★★先定义一个私有对象
def __new__(cls):
if cls.__obj is None:
cls.__obj = object.__new__(cls)
return cls.__obj
"""
有这个对象直接返回,没这个对象,就给你创建,保证只有一个
第一次实例化时,if cls.__obj is None 条件为真 , 创建一个对象放到cls.__obj , 最后返回
第二次实例化时,if cls.__obj is None 条件为假 , 直接返回
第三次实例化时,if cls.__obj is None 条件为假 , 直接返回
第三次实例化时,if cls.__obj is None 条件为假 , 直接返回
"""
obj1 = Singleton()
print(obj1)
obj2 = Singleton()
print(obj2)
obj3 = Singleton()
print(obj3)
obj4 = Singleton()
print(obj4)
(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("小强")
obj2 = Singleton('校长')
print(obj1.name)
print(obj2.name)
结果都是校长
"""
obj1 = Singleton("小强") self.name = "小强"
obj2 = Singleton("校长") self.name = "校长"
obj1 和 obj2 都是同时指向同一个对象,因为对象只创建了一个
对象.name 是获取他后边校长那个值(替换),是同一个值打印了2次;
“”"
### del 魔术方法(析构方法)
'''
#一般用于查看文件★★★★★
触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
功能:对象使用完毕后资源回收
参数:一个self接受对象
返回值:无
'''
class LangDog():
food = "吃肉"
def __init__(self,name):
self.name = name
def __del__(self):
print("析构方法被触发..")
#(1) 页面执行完毕回收所有变量
obj = LangDog("刀疤")
print(obj.name)
#(2) 所有对象被del的时候
"""
当一个值,没有任何变量指向或者说引用,这个值才会被真正的释放
"""
other_obj = obj
print("<==start==>")
del obj
del other_obj
print("<==end==>")
模拟文件操作(del可以做事后工作)
fp = open(文件,模式,编码)
fp.read()
fp.close()
import os
class ReadFile():
def __new__(cls,filename):
#new是创建一个对象,创建的时候可以先判断文件有没有
# 判断文件是否存在
if os.path.exists(filename):
return object.__new__(cls)
else:
return print("该文件是不存在的")
def __init__(self,filename):
# 打开文件操作(要在初始化完成)
self.fp = open(filename,mode="r",encoding="utf-8")
def readcontent(self):
# 读取文件操作
content = self.fp.read()
return content
def __del__(self):
self.fp.close()
obj = ReadFile("ceshi.txt")
res = obj.readcontent()
print(res)
###str 魔术方法
'''
触发时机: 使用print(对象)或者str(对象)的时候触发
功能: 查看对象
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
'''
class Cat():
gift = "传说中的小猫有九条命,喜欢卖萌和上树"
def __init__(self,name):
self.name = name
def __str__(self):
return self.cat_info()
def cat_info(self):
return "{}小猫有故事-{}".format(self.name,self.gift)
tom = Cat("汤姆")
触发方式一, print 打印该对象
print(tom)
触发方式二, str
res = str(tom)
print(res)
###repr 魔术方法
'''
触发时机: 使用repr(对象)的时候触发
功能: 查看对象,与魔术方法__str__相似
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
'''
class Mouse():
gift = "打洞"
def __init__(self,name):
self.name = name
def __repr__(self):
return self.mouse_info()
def mouse_info(self):
return "{}老鼠天赋是{},龙生龙,凤生凤,老鼠的儿子会打洞".format(self.name,self.gift)
# 在系统底层,如果定义了repr , 将会默认赋值给str方法.
# __str__ = __repr__
repr强转obj对象时触发
obj = Mouse("杰瑞")
res = repr(obj)
print(res)
注意点 底层存在赋值调用给str的语法,所以能实现打印或者str强转对象的触发机制.
print(obj)
res = str(obj)
print(res)
###call 魔术方法
#如果类中方法比较多,对象调用起来麻烦,可以用call,把方法集中(调)到call里面通一调用,有参数要带上参数★★★★★
#可以模拟内置方法★★★★★
'''
触发时机:把对象当作函数调用的时候自动触发,(对象中的参数要和call一一对应,call不包括sell参数,要一一对应)
功能: 模拟函数化操作
参数: 参数不固定,至少一个self参数
返回值: 看需求
'''
(1) 基本用法
class MyClass():
a = 1
""""""
def __call__(self):
print("call魔术方法被触发..")
obj = MyClass()
obj()
(2) 模拟洗衣服的过程
class Wash():
# 用call魔术方法统一调用
#调用时,有参数要带上参数
def __call__(self,something):
self.step1(something)
self.step2()
self.step3()
def step1(self,something):
print("脱衣服,洗{}".format(something))
def step2(self):
print("放水里,扔点洗衣液,洗衣粉,蓝月亮")
def step3(self):
print("扭干净,穿上")
obj = Wash()
obj("裤衩")
"""
obj.step1("裤衩")
obj.step2()
obj.step3()
obj.step3()
(3) 模拟内置方法 int 实现myint
import math
class MyInt():
def mycalc(self,num,sign=1):
#sign默认为1
# 去掉左边多余的0
strvar = num.lstrip("0")
if strvar == "":
return 0
# 计算最终的结果
return eval(strvar) * sign
def __call__(self,num):
# 判断是布尔类型
if isinstance(num,bool):
if num == True:
return 1
else:
return 0
# 判断是整型
elif isinstance(num,int):
return num
# 判断是浮点型
elif isinstance(num,float):
# 方法一
'''
strvar = str(num)
return strvar.split(".")[0]
'''
# 方法二
"""
if num >= 0 :
return math.floor(num)
else:
return math.ceil(num)
"""
return math.floor(num) if num >= 0 else math.ceil(num)
elif isinstance(num,str):
# 首字符是+或者- 后边的是纯数字字符串
if (num[0] == "+" or num[0] == "-") and num[1:].isdecimal():
if num[0] == "+":
sign = 1
else:
sign = -1
#把要处理的符号和符号后面的纯数字字符串放到调用处
return self.mycalc(num[1:],sign)
#调用的时候要把操作的数据写到调用参数中,然后要与调用函数(除了self参数)的参数一一对应,函数操作以后,将调用参数的值赋给函数参数
#如果调用的时候没有参数就不用写
#在类的内部,函数除了self参数要一一对应,在外部,对象可以作为一个参数与self对应,在类的内部调用要用self调用
elif num.isdecimal():
return self.mycalc(num)
else:
return "老铁,这个真不能转~"
myint = MyInt()
print( myint(0) ) #=> 3
print( myint(3.13) ) #=> 3
10 * 1 = 10
10 * -1 = -10
print(eval("3"))
strip
lstrip
rstrip
### __bool__魔术方法
'''
触发时机:使用bool(对象)的时候自动触发
功能:强转对象
参数:一个self接受当前对象
返回值:必须是布尔类型
类似的还有如下等等(了解):
__complex__(self) 被complex强转对象时调用
__int__(self) 被int强转对象时调用
__float__(self) 被float强转对象时调用
...
class MyClass():
def __bool__(self):
return True
obj = MyClass()
res = bool(obj)
print(res)
add 魔术方法 (与之相关的__radd__ 反向加法)
'''
触发时机:使用对象进行运算相加的时候自动触发
功能:对象运算
参数:二个对象参数
返回值:运算后的值
类似的还有如下等等(了解):
__sub__(self, other) 定义减法的行为:-
__mul__(self, other) 定义乘法的行为:
__truediv__(self, other) 定义真除法的行为:/
...
class MyAdd():
def __init__(self,num):
self.num = num
# 对象在加号+左侧的时,自动触发
def __add__(self,other):
return self.num + other
#对象在+号右侧时,自动触发
def __radd__(self,other):
return self.num + other*2
a = MyAdd(7)
情况一
res = a + 7
self 接受a other接受7 , 触发的是__add__方法
情况二
res = 7 + a
self 接受a other接受7 , 触发的是__radd__方法
情况三
"""
a+b 先触发 __add__ ,self 接受的7 , other 接受的是b
res = 7+b
7+b 再触发 __radd__ ,self 接受的b , other 接受的是7
return 8+7*2 = 22
res = 22
"""
b = MyAdd(8)
res = a+b
len 魔术方法
'''
触发时机:使用len(对象)的时候自动触发
功能:用于检测对象中或者类中成员的个数
参数:一个self接受当前对象
返回值:必须返回整型
类似的还有如下等等(了解):
__iter__(self) 定义迭代容器中的元素的行为
__reversed__(self) 定义当被 reversed() 调用时的行为
__contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
'''
计算一下类中所有自定义成员的个数
思路:__dict__查看内部成员结构,有自定义的和系统自带的(两边是双下划线属于系统自带的),返回是一个字典,通过for循环,可以得到字典的键,然后过滤掉左右两边有下划线的键,把剩下的键添加到新的列表里通过len就可以得到长度★★★★★
class MyClass():
pty1 = 1
pty2 = 2
__pty3 = 3
def func1():
pass
def func2():
pass
def __func3():
pass
def func4():
pass
def __len__(self):
# print(MyClass.__dict__)
# lst = []
# for i in MyClass.__dict__:
# print(i)
# if not( i.startswith("__") and i.endswith("__") ):
# lst.append(i)
# print(lst)
# 简写
lst = [i for i in MyClass.__dict__ if not( i.startswith("__") and i.endswith("__") )]
return len(lst)
obj = MyClass()
print( len(obj) )