Python 基础之面向对象之常用魔术方法

魔术方法

1.__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()

2.__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__

2.2.2单态模式
无论实例化多少次,都有且只有一个对象
最终目的:为了节省内存空间,应用的场景是只调用相关的成员属性或方法,而不用动态添加成员属性方法的环境中‘‘‘
__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

3.__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) 1.页面执行完毕回收所有变量
obj = Dog("Lwhite")
obj.eat("bone")
print("=======")

#(2)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:例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的效果是,让你输入内容的文件名,如果这个文件名存在,继续输入内容,如果不存在会自动创建一个并

让其输入内容,输入后返回输出输入的内容结果,也可以在文件中进行查看,内容已经写到文件中.

4.__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)

5.__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)
6.__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)

7. __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)
8.__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
9. __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}
"""

魔术方法

1.__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()

1. __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__

2.2.2单态模式
无论实例化多少次,都有且只有一个对象
最终目的:为了节省内存空间,应用的场景是只调用相关的成员属性或方法,而不用动态添加成员属性方法的环境中‘‘‘
__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

3.__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) 1.页面执行完毕回收所有变量
obj = Dog("Lwhite")
obj.eat("bone")
print("=======")

#(2)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:例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的效果是,让你输入内容的文件名,如果这个文件名存在,继续输入内容,如果不存在会自动创建一个并让其输入内容,输入后返回输出输入的内容结果,也可以在文件中进行查看,内容已经写到文件中.

4.__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)

5.__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)
6.__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)

7. __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)
8.__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
9. __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}
"""

原文地址:https://www.cnblogs.com/hszstudypy/p/10925612.html

时间: 2024-09-28 20:44:01

Python 基础之面向对象之常用魔术方法的相关文章

面向对象中的常用魔术方法

__autoload($classname);这个魔术方法与其他魔术方法不同的是,它不是在类中使用的,其他都是在类内部使用,只要在页面中用到一个类,就会自动将这个类名传给这个函数的参数.在开发中用它来自动加载类. __sleep():是在对象序列化也叫串行化时,自动调用的方法,因为对象序列化的时候serialize($object),如果类里不加这个魔术方法,会自动将类中的所有属性全部序列化,如果只想让某些属性被序列化,就要用到这个方法,这个方法返回一个由类的属性组成的数组.序列哪个属性就将那个

python常用魔术方法概览

构造和初始化 __init__(self, args) 构造函数 __new__(cls) 传入的是类实例 __del__(self) 析构函数,调用 del cls 时会被调用 属性访问控制 __getattr__(self, name) 如果属性已经定义了那么不会再执行__getattr__()了,而是直接通过访问实例字典返回结果,__getattr__()只在访问未定义的属性时被触发 __setattr__(self, name, value) 直接给属性赋值 cls.name = val

Day6 - Python基础6 面向对象编程

Python之路,Day6 - 面向对象学习 本节内容: 面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀,人狗作战,那至少需要2个角色,一个是人, 一个是狗,且人和狗都有不同的技能,比如人拿棍打狗, 狗可以咬人,怎么描述这种不同的角色和他们的功能呢? 你搜罗了自己掌握的所有技能,写出了下面的代码来描述这两个角色 1 2 3 4 5 6 7 8 9 10 11

Python基础09 面向对象的进一步拓展

Python基础09 面向对象的进一步拓展 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们熟悉了对象和类的基本概念.我们将进一步拓展,以便能实际运用对象和类. 调用类的其它信息 上一讲中提到,在定义方法时,必须有self这一参数.这个参数表示某个对象.对象拥有类的所有性质,那么我们可以通过self,调用类属性. class Human(object): laugh = 'hahahaha' def show_laugh(

php中的常用魔术方法总结

以下是对php中的常用魔术方法进行了详细的总结介绍,需要的朋友可以过来参考下 常用的魔术方法有:__Tostring ()  __Call()  __autoLoad()  __ clone()  __GET()   __SET()    __isset()  __unset() 1.__Tostring()   用于定义输出对象引用时调用  常用于打印一些对象的信息 必须有返回值eg:有一个persion类Persion per =new persion()Echo per;    //直接调

Python(27)_字符串的常用的方法2

#-*-coding:utf-8-*- ''' 字符串操作 ''' s = " bowen " # 从右边删 s1 = s.rstrip() print(len(s1)) s2 = s1.lstrip() print(len(s2)) 从右边删除元素,从左边删除元素,这个在以后项目中经常用到 · 计算个数 #-*-coding:utf-8-*- ''' 字符串操作 ''' s = " boaaweushvaan " s1 = s.count('a') print(s

python基础之面向对象高级编程

面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个"函数"供使用(可以讲多函数中公用的变量封装到对象中) 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数 面向对象三大特性:封装.继承和多态 本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员. 类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有

Python基础教程(第九章 魔法方法、属性和迭代器)

本文内容全部出自<Python基础教程>第二版,在此分享自己的学习之路. ______欢迎转载:http://www.cnblogs.com/Marlowes/p/5437223.html______ Created on Marlowes 在Python中,有的名称会在前面和后面都加上两个下划线,这种写法很特别.前面几章中已经出现过一些这样的名称(如__future__),这种拼写表示名字有特殊含义,所以绝不要在自己的程序中使用这样的名字.在Python中,由这些名字组成的集合所包含的方法称

Python基础08 面向对象的基本概念

Python基础 面向对象的基本概念 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 谢谢逆水寒龙,topmad和Liqing纠错 Python使用类(class)和对象(object),进行面向对象(object-oriented programming,简称OOP)的编程. 面向对象的最主要目的是提高程序的重复使用性.我们这么早切入面向对象编程的原因是,Python的整个概念是基于对象的.了解OOP是进一步学习Python