zoukankan      html  css  js  c++  java
  • python 内置方法/魔法方法

    什么是内置方法?

    # 定义在类内部,以__开头并以__结果的方法
    # 特点:会在某种情况下自动触发执行

    为什么要用内置方法?

    # 为了定制化我们的类or对象

    python中常用魔法方法

    # __init__:类实例化会触发
    # __str__:打印对象会触发
    # __call__:对象()触发,类也是对象  类(),类的实例化过程调用元类的__call__
    # __new__:在类实例化会触发,它比__init__早(造出裸体的人,__init__穿衣服)
    # __del__:del 对象,对象回收的时候触发
    # __setattr__,__getattr__:(.拦截方法),当对象.属性--》赋值会调用setattr,如果是取值会调用getattr
    # __getitem__,__setitem__:([]拦截)
    # __enter__和__exit__ 上下文管理器

    如何使用内置方法?

    __str__:在打印对象时会自动触发,然后将返回值(必须是字符串类型)当做本次打印的结果输出

    class People:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __str__(self):
            # print('运行了...')
            return "<%s:%s>" %(self.name,self.age)
    
    
    obj = People('辣白菜同学', 18)
    
    # print(obj.__str__())
    print(obj)  # <'辣白菜同学':18>

    __del__:在清理对象时触发,会先执行该方法

    class Point:
        def __init__(self, x=0, y=0):
            self.x = x
            self.y = y
    
        def __del__(self):
            class_name = self.__class__.__name__
            print(class_name, "销毁")
    
    pt1 = Point()
    pt2 = pt1
    print(id(pt1),id(pt2))    # 打印对象的id
    del pt1      #要等pt2执行完才会触发__del__
    print(pt2)
    
    '''
    2074762969384 2074762969384
    <__main__.Point object at 0x000001E311828128>
    Point 销毁
    '''

     __format__:自定义打印时间格式

    date_dic={
        'ymd':'{0.year}:{0.month}:{0.day}',
        'dmy':'{0.day}/{0.month}/{0.year}',
        'mdy':'{0.month}-{0.day}-{0.year}',
    }
    class Date:
        def __init__(self,year,month,day):
            self.year=year
            self.month=month
            self.day=day
    
        def __format__(self, format_spec):
            if not format_spec or format_spec not in date_dic:
                format_spec='dmy'
            fmt=date_dic[format_spec]
            return fmt.format(self)
    
    d1=Date(2016,12,29)
    print(format(d1))
    print(format(d1,"mdy"))
    
    '''
    执行结果
    29/12/2016
    12-29-2016
    '''

    setattr,getattr,setitem,getitem演示

    setitem、getitem

    class Person:
        def __init__(self,name):
            self.name=name
        def __setitem__(self, key, value):
            setattr(self,key,value)  #反射
        def __getitem__(self, item):
            return getattr(self,item) # 反射取值
    
    p=Person('lqz')
    # p.name='ppp'
    p['name']=10 # 本来这么赋值是不可以的,如何就可以了呢,重写__setitem__魔法方法
    # print(p.name)
    
    print(p['name'])

    __setattr__、__getattr__

    class Mydic(dict):
        def __setattr__(self, key, value):
            print("对象加点赋值,会触发我")
            self[key]=value
        def __getattr__(self, item):
            print("对象加点取值,会触发我")
            return self[item] # 不要加引号
    
    mydic=Mydic(name='lqz',age=18)
    # print(mydic['name'])
    print(mydic.name)
    # mydic.name=99
    # print(mydic.name)

    案例:

    class Fun():
        def __init__(self,name,age,male):
            self.name = name
            self.age = age
            self.male = male
    
        def __setattr__(self, key, value):
            if key == "name":
                if isinstance(value,str):
                    super().__setattr__(self, key, value)
                else:
                    print("不能赋值非字符串类型")
            else:
                super.__setattr__(self, key, value)
    
        def __getattr__(self, item):
            print("加点取值会调用我")
            print(type(self.__dict__),self.__dict__)
            return self.__dict__.get(item)
    
    fun = Fun("lxx",18,"male")
    fun.name = 13
    print(fun.age)

    with 上下文管理器(__enter__、__exit__)

    class Person:
        def __enter__(self):
            print("我在with管理的时候,会触发")
            print('进入with语句块时执行此方法,此方法如果有返回值会赋值给as声明的变量')
            return 'oo'
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('退出with代码块时执行此方法')
            print('1', exc_type)
            print('2', exc_val)
            print('3', exc_tb)
    
    
    with Person() as p:   # 这句话执行,会触发类的__enter__,这个p就是上面__enter__中return的
        print(p)

    案例:上下文管理MySQL链接

    import pymysql
    
    class Mysql:
        def __enter__(self):
            print("我在with管理的时候,会触发")
            print('进入with语句块时执行此方法,此方法如果有返回值会赋值给as声明的变量')
            # 链接
            self.conn = pymysql.connect(
                host='127.0.0.1',
                port=3306,
                user='root',
                password='123456',
                database='book_user',
                charset='utf8',
            )
            # 游标
            self.cursor = self.conn.cursor()  # 执行完毕返回的结果集默认以元组显示
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.cursor.close()
            self.conn.close()
            print('退出with代码块时执行此方法')
            # print('1', exc_type)
            # print('2', exc_val)
            # print('3', exc_tb)
    
    
    with Mysql() as self:   # 这句话执行,会触发类的__enter__
        print(self)
        sql = 'select * from app01_book;'
        rows = self.cursor.execute(sql)
        print(rows)

     __eq__

    class A:
        def __init__(self,x,y):
            self.x = x
            self.y = y
    
        # def __eq__(self,obj):
        #     # 打印出比较的第二个对象的x值
        #     print(obj.x)
        #     if self.x +self.y == obj.x+obj.y:
        #         return True
        #     else:
        #         return False
    
    a=A(1,2)
    b=A(99,3)
    print(a==b)   # 当执行==s时,会触发__eq__的执行,并且把b传进去,就是object
    # ==后只要是对象,就可以传进去,就是object
  • 相关阅读:
    WC2021 游记
    TC11054
    P5904
    CF741D
    CF1467 题解
    [CTSC2008]网络管理 [树剖+整体二分]
    [HNOI2015]接水果[整体二分]
    [SDOI2010]粟粟的书架 [主席树]
    整体二分的一些见解[整体二分学习笔记]
    P2710 数列[fhq treap]
  • 原文地址:https://www.cnblogs.com/baicai37/p/12706127.html
Copyright © 2011-2022 走看看