Python笔记_20_魔术方法

魔术方法(特定时机自动触发)

__init__ (构造方法)
  • 触发时机:实例化对象,初始化的时候触发
  • 功能:为对象添加成员,用来初始化的
  • 参数:参数不固定,至少一个self参数
  • 返回值:无
  1. 基本用法
class MyClass():
	def __init__(self):
		# print(1111)
		self.name = "张国成"

# 实例化对象  [类的实例化]
obj = MyClass()
print(obj.name)
  1. __init__ 可以传递多个参数
class MyClass():
	def __init__(self,name):
		# self.name 这个name 是成员属性name
		# self.name = name 后面的name 是传进来的参数
		self.name = name

# 类的实例化  实例化对象
# 把参数传递到MyClass后面的这个括号里
obj = MyClass("陈广耀")
print(obj.name)
  1. 综合案例
    类可以是一个,但对象可以是多个.对象之间彼此独立
class Children():
	def __init__(self,name,skin):
		self.name = name
		self.skin = skin
		
	def eat(self):
		print("小孩生下来的时候,手里拿了大串大腰子")
		
	def drink(self):
		print("小孩生下来,手里拿了两瓶啤酒")
		
	def beat_doudou(self):
		print("小孩生下来就喜欢打豆豆")

	def obj_info(self):
		print("小孩的姓名:{},小孩的肤色是{}".format(self.name,self.skin))
'''
同一个类产生了三个对象,但是每个对象彼此都是独立的
而且都可以调用类中的公有成员属性方法.
'''
child1 = Children("方贵权","黑色的")
child1.obj_info()
child1.eat()

child2 = Children("张国成","屎黄色")
child2.obj_info()
child2.drink()

child3 = Children("王宝强","绿色的")
child3.obj_info()
child3.beat_doudou()
__new__魔术方法
  • 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
  • 功能:控制对象的创建过程
  • 参数:至少一个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(obj.abc)
  1. 对比 __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("王俊文", "舒畅", "境泽年", "五金玲", name="Anglelababy")

  1. 如果通过__new__返回的是其他类的对象,不会触发自己本类的__init__
    ‘’‘因为__init__初始化的是本类对象’’’
class Boat():
    def __new__(cls, *args, **kwargs):
        return obj2

    def __init__(self):
        print("init调用了")


obj = Boat()
print(obj.abc)
__del__(析构方法)
  • 触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
  • 功能:对象使用完毕后资源回收
  • 参数:一个self接受对象
  • 返回值:无
import os


class LangDog():
    def __init__(self, name):
        self.name = name

    def eat(self, something):
        print("可爱的小狼{},喜欢吃{}".format(self.name, something))

    def __del__(self):
        print("__del__方法被触发")
  1. 页面执行完毕回收所有变量
obj = LangDog("詹姆斯·狗蛋")
obj.eat("屎")
print("<===>")
  1. 所有对象被del的时候

    只有当所有指向该对象的变量都删除的时候,才算真正的删除该对象

obj2 = obj
print("<==start===>")
del obj
del obj2
print("<==end===>")
  1. 用类来模拟文件写的操作
fp = open("ceshi111.txt",mode="w",encoding="utf-8")
fp.write("sfdsdf")
fp.close()

fp = open("ceshi111.txt",mode="r",encoding="utf-8")
res = fp.read()
fp.close()
print(res)

print("<=111==>")


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)
__call__ 魔术方法
  • 触发时机:把对象当作函数调用的时候自动触发
  • 功能: 模拟函数化操作
  • 参数: 参数不固定,至少一个self参数
  • 返回值: 看需求

1.基本语法




class MyClass():
    def __call__(self):
        print("__call__方法被调用")
        return "done"


obj = MyClass()
res = obj()
print(res)
  1. 模拟洗衣服的过程
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()

# 小王是个快乐的孩子
obj("裤衩")
  1. 模拟内置int方法实现myint
# print(int(-5.9))

import math

class MyInt():

    def stoi(self, n, sign=1):
        res = n.lstrip("0")
        if res == "":
            return 0
        num = eval(res) * sign
        return num

    def __call__(self, n):
        # 判断的是布尔类型
        if isinstance(n, bool):
            if n:
                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
                elif n[0] == "-":
                    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 = eval("123454")
# print(res,type(res))
res = myint("12345")
print(res,type(res))

# res = int("-00000000000111222abcdfrf")
# print(res)

res = myint("+00000000000111222")
res = myint("*&^%$#@00000000000000000")
print(res)
# res = int("*&^%$#@00000000000000000")
# res = eval("")
# print(res)
res = int(5 + 6)
print(res)
res = myint(5 * 6)
print(res)
res = myint([1,3,4])
res = int([1, 3, 4])
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__(self)   被complex强转对象时调用
__int__(self)       被int强转对象时调用
__float__(self)     被float强转对象时调用

class MyBool():
	def __bool__(self):
		print(122)
		# return True
		return False


obj = MyBool()
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

	# 对象+数值,并且对象在+加号的左边,自动触发__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(3)
res = a + 56
print(res)


# 2.当对象在加号的右侧  自动触发radd 方法
b = MyAdd(5)
res = 33 + b
print(res)

# 3 a+b =?
res = a + b
print(res)
'''
a在加号的左侧,触发add魔术方法
self.num + other => 3 + b

b在加号的右侧,触发radd魔术方法
res = 3+b
self.num + other * 10 => 5 + 3 *10 => 35

'''
__len__ 魔术方法
  • 触发时机:使用len(对象)的时候自动触发
  • 功能:用于检测对象中或者类中某个内容的个数
  • 参数:一个self接受当前对象
  • 返回值:必须返回整型

类似的还有如下等等(了解):
__iter__(self)           定义迭代容器中的元素的行为
__reversed__(self)       定义当被 reversed() 调用时的行为
__contains__(self, item)   定义当使用成员测试运算符(in 或 not in)时的行为

用len(对象)方式,算出该对象所归属的类有多少自定义成员

class MyLen():
	pty1 = 1
	pty2 = 2
	__pty3 = 3

	def func1():
		pass

	def func2():
		pass

	def __func3():
		pass

	def __func4():
		pass

	def __func5():
		pass

	def __len__(self):
		# print(MyLen.__dict__)
		dic = MyLen.__dict__
		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)
"""
{'__module__': '__main__',
'pty1': 1, 'pty2': 2,
 '_MyLen__pty3': 3,
 'func1': <function MyLen.func1 at 0x7f10880d9620>, 'func2': <function MyLen.func2 at 0x7f10880d96a8>,
 '_MyLen__func3': <function MyLen.__func3 at 0x7f10880d9730>, '__len__': <function MyLen.__len__ at 0x7f10880d97b8>,
 '__dict__': <attribute '__dict__' of 'MyLen' objects>,
 '__weakref__': <attribute '__weakref__' of 'MyLen' objects>, '__doc__': None}
"""
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值