Python魔术方法简述

这篇文章介绍魔术方法。

目录

1. __enter__ 和 __exit__ 实现上下问管理器

2. __str__ 和 __repr__方法

3. __add__ 和 __sub__ 方法

4. __call__ 方法

5.__new__方法


1. __enter__ 和 __exit__ 实现上下问管理器

class OpenFile(object):

    def __init__(self, file_name, mode, encoding='utf-8'):
        self.file_name = file_name
        self.mode = mode
        self.encoding = encoding

    def __enter__(self):
        print("上下文管理器进入方法")
        self.obj_f = open(file=self.file_name, mode=self.mode, encoding=self.encoding)
        return self.obj_f

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.obj_f.close()
        print("上下文管理器退出方法")
        print(exc_type)  # 异常类型
        print(exc_val)  # 异常值
        print(exc_tb)  # 异常溯源信息


with OpenFile("test1.txt", 'a') as f:
    f.write('121218938219382193')
    print("使用方法")
    print(f)
    # print(name)

这里使用的__enter__ 和 __exit__ 方法来实现上下文管理器的,不用手动地去关闭文件,在__exit__中做相关关闭的操作即可。

使用__enter__ 和 __exit__ 实现连接MySQL数据库的实例:

def do_config():
    """
    从配置文件中读取数据库的配置
    :return:
    """
    return '数据库配置'


# 第一题
class MyDb(object):
    def __init__(self, host, user, password, db, port, charset):
        self.host = do_config("database", "host")
        self.user = do_config("database", "user")
        self.password = do_config("database", "password")
        self.db = do_config("database", "db")
        self.port = do_config("database", "port")
        self.charset = do_config("database", "charset")

    def __enter__(self, sql, args=None, is_all=False):
        self.cursor = self.conn.cursor()
        self.cursor.execute(sql, args)
        self.conn.commit()
        if not is_all:
            try:
                res = self.cursor.fetchall()  # 表示获取数据中的所有记录
            except Exception as e:
                raise e
        else:
            try:
                res = self.cursor.fetchone()  # 表示只取数据中的一条记录
            except Exception as e:
                raise e
        return res

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cursor.close()  # 关闭数据库游标
        self.conn.close()    # 关闭数据库连接

2. __str__ 和 __repr__方法

都是用来格式化输出对象的,本质上并无任何区别,但是在不同情景下会调用不同的方法

str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常

class MyClass(object):
    def __str__(self):
        print("acc")

    def __repr__(self):
        return "__repr__的返回方法"

# 目的是:
# 可以在类中定义__str__方法,做当前类的说明
# str总共有3种触发方法
m1 = MyClass()
# 第1种:直接打印触发
print(m1)
# 第2种:通过str转换对象为字符串时触发
res = str(m1)
print(res)
# 第3种:通过format内置函数处理对象时触发
res2 = format(m1)
print(res)

# repr的触发方法
# 1. 交互环境下直接输入对象,会触发repr方法
# 2. repr内置函数处理对象时会触发repr方法
# 3. str方法的备胎

3. __add__ 和 __sub__ 方法

(1)使用 __add__ 和 __sub__ 实现两个字符串的相加和相减。

class MyStr(object):
    def __init__(self, value):
        self.value = value

    def __add__(self, other):
        """
        实现两个字符串的拼接
        :param other: 另一个字符串
        :return: 字符串拼接结果
        """
        res = '{}{}'.format(self, other)
        return res

    def __sub__(self, other):
        """
        字符串相减
        :param other:第二个字符串
        :return: 从第一个字符串中减去第二个字符串
        """
        return str(self).replace(str(other), '')

    def __str__(self):
        return self.value


s1 = MyStr('abcde')
s2 = MyStr('12345')
s3 = MyStr('abcde12345')
print(s1 + s2)
print(s3 - s2)
# 执行结果
abcde12345
abcde

(2)使用 __add__ 和 __sub__ 实现两个字典的相加和相减

class MyDic(dict):
    """实现两个字典的相加和相减"""
    def __add__(self, other):
        """实现相加"""
        new_dict = self.copy()
        new_dict.update(other)
        return MyDic(new_dict)

    def __sub__(self, other):
        """实现相减"""
        new_dict = self.copy()
        for key in other.keys():
            if key in new_dict.keys():
                new_dict.pop(key)

        return new_dict

testDic1 = MyDic({'a': '111', 'b': '222'})
testDic2 = MyDic({'a': '111', 'b': '111',  'c': '222'})

res = testDic1 + testDic2
print(res)
res2 = testDic2 - testDic1
print(res2)

4. __call__ 方法

直接使用实例对象后面跟上参数,即可使用类。

class MyCall:
    """实现__call__方法"""
    def __init__(self):
        pass

    def __call__(self, a, b, *args, **kwargs):
        result = a + b
        print(result)


if __name__ == '__main__':
    m = MyCall()
    m(100, 111)

5.__new__方法

class MyNew:
    def __init__(self, num=None):
        self.num = num
        print("__init__方法被调用")

    def __new__(cls, *args, **kwargs):
        print("__new__方法被调用")
        return object.__new__(cls)

    def add(self, a, b):
        print(a + b + self.num)


new1 = MyNew(1)
new1.add(1, 2)

各个方法被调用的时间总结:

__new__ :在创建对象时会被调用

__str__ :在print打印对象的时候调用

__repr__:repr函数处理,或者控制台输入时 

__call__:对象加括号调用的时候触发

<完>

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值