zoukankan      html  css  js  c++  java
  • 面向对象进阶---魔术方法

    内置方法 双下方法 魔术方法:
      都是python的对象内部自带的
      并且都不需要我们自己去调用它

    1.  __str__  __repr__:改变对象的字符串显示   输出的类型为str

    class Course:
        def __init__(self, name, price, period):
            self.name = name
            self.price = price
            self.period = period
    
        def __repr__(self):  # 备胎
            return '%s,%s,%s' % (self.name, self.price, self.period)    #return 类型必须是str
    
        def __str__(self):
            return self.name      #return的类型必须是str
    
    
    python = Course('python', 25000, '6 months')
    print(python)               #-->python
    print('course %s' % python) #-->course python
    
    print(repr(python))         #-->python,25000,6 months
    print('course %r' % python) #-->course python,25000,6 months

      总结:   

      如果__str__存在,__repr__也存在
        那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__
        而repr(obj)和%r格式化字符串,都会调用__repr__
      如果str不存在,repr存在
        那么print(obj),字符串格式化format,%s,%r 和repr(obj)都调用__repr__
      如果str存在,repr不存在
        那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__
        repr(obj)和%r格式化字符串 都会打印出内存地址


    class Course(object):
        def __init__(self,name,price,period):
            self.name = name
            self.price = price
            self.period = period
    
        def __repr__(self):   # 备胎
            return '%s,%s,%s'%(self.name,self.price,self.period)      #return类型必须是str
    
        def __str__(self):
            return self.name      #return类型必须是str
    
    class Python(Course):
        pass
        def __repr__(self):   # 备胎
            return '%s--%s--%s'%(self.name,self.price,self.period)
    
        # def __str__(self):
        #     return '全栈开发 :'+self.name
    
    py20 = Python('python',25000,'6 months')
    print(py20)
    # 打印对象 先走自己的__str__,如果没有,走父类的,如果除了object之外的所有父类都没有str
    # 再回来,找自己的__repr__,如果自己没有,再找父类的,如果父类也没有,就打印内存地址
    repr是str的备胎
    和所有的字符串格式化以及直接打印这个对象相关 推荐使用repr

    2. __new__ 构造方法  生产对象的时候用的 - 单例模式
      实例化一个Foo的对象
      先开辟一块儿空间,使用的是Foo这个类内部的__new__
      如果我们的Foo类中是没有__new__方法的,则调用object类的__new__方法
    
    
    class Foo:
        def __new__(cls, *args, **kwargs):   #cls永远不会使用self参数,因为self 是这之后才被创建出来的 
            print('in new')  # 先执行  
            obj = object.__new__(cls)      #self空间在这一步才创建出来
            print(obj)  
            return obj               #将创建出来的空间返回给self 
    
        def __init__(self):
            print('init')
            print(self)  # 后执行    
    Foo()
    '''
    in new
    <__main__.Foo object at 0x000001D5A4A27400>    
    init
    <__main__.Foo object at 0x000001D5A4A27400>  obj和self内存地址一样
    '''
     单例模式:
        一个类有且只能有一个实例:可以被实例化多次 但是保留最后一次实例化的属性
     
    #单例模式
    class A:
        __flag = None          #创建一个静态变量来指向同一内存空间 
        def __new__(cls, *args, **kwargs):
            if cls.__flag is None:    #首次没有内存空间就创建一个新的  如果有就不在创建
                cls.__flag = object.__new__(cls)
            return cls.__flag
    
        def __init__(self,name=None,age=None):
         if name: self.name
    = name if age: self.age = age a1 = A('alex',84) print(a1) #<__main__.A object at 0x00000241BF577BA8> a2 = A('alex',83) print(a2) #<__main__.A object at 0x00000241BF577BA8> a3 = A('alex') print(a3) #<__main__.A object at 0x00000241BF577BA8> print(a1.__dict__) #{'name': 'alex', 'age': 83} print(a2.__dict__) #{'name': 'alex', 'age': 83} print(a3.__dict__) #{'name': 'alex', 'age': 83} # 保证一个类无论 被实例化多少次,只开辟一次空间,始终使用的是同一块内存地址
    
    

     3. __del__方法

    import time
    
    class A:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __del__(self):
            # 只和del obj语法有关系,在执行del obj之前会来执行一下__del__中的内容
            print('执行我啦')
    
    a = A('alex', 84)
    print(a.name)
    print(a.age)
    del a  # 手动删除对象a 就直接执行__del__ 
    time.sleep(1)
    # 如果不手动执行del 会在所有代码执行完成后 自动执行del a 这时候就会先睡一秒在打印'__del__'中的内容
    # 在所有的代码都执行完毕之后,所有的值都会被python解释器回收
    python解释器清理内存:
      1.我们主动删除 del obj
      2.python解释器周期性删除
      3.在程序结束之前 所有的内容都需要清空
      既然python解释器可以周期性的清理内存 为什么我们还要手动去删除一些数据呢?
      因为在
    归还一些操作系统的资源的时候还有包括文件网络数据库连接的时候使用,
      我们需要先将这些接口关闭了之后再删除内容,不然内容删除了,这些打开的接口依然存在,会影响后面对系统资源等一些数据的调用
    import time
    class A:
        def __init__(self,path):
            self.f = open(path,'w')
        def __del__(self):
            '''归还一些操作系统的资源的时候使用'''
            '''包括文件网络数据库连接'''
            print(111)
            self.f.close()    #在删除内存的时候执行__del__ 先将文件接口关闭
    
    
    a = A('userinfo')
    time.sleep(1)

    4. __call__

    class A:
        def call(self):     #当然也可以自己手动写一个call方法实现和__call__一样的功能
            print('in call')
    
        def __call__(self, *args, **kwargs):
            print('in __call__')
    
    
    A()()           #实例化+调用  相当于obj = A()和obj()
    #如果没有__call__会报错 'A' object is not callable
    obj = A()
    obj.call()      #调用自己写的call方法实现和__call__一样的功能
    5 __enter__和__exit__ 用在with的上下文处理
     
    class File:
        def __enter__(self):
            print('start')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('exit')
    
    with File():
        print('wahaha')
        
    '''
    输出:
    start
    wahaha
    exit
    
    

    和with组合编写一个文件操作类:

    import pickle
    
    
    class Mypickle_dump:        #写文件
        def __init__(self, path, mode='ab'):
            self.path = path
            self.mode = mode
    
        def __enter__(self):
            self.f = open(self.path, self.mode)
            return self
    
        def dump(self, value):
            pickle.dump(value, self.f)
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.f.close()
    
    
    with Mypickle_dump('mypickle', 'ab')as f:    #读文件
        f.dump('1')
        f.dump('2')
        f.dump('3')
        f.dump('4')
        f.dump('你好啊')
    
    
    class Mypickle_load:
        def __init__(self, path, mode='rb'):
            self.path = path
            self.mode = mode
    
        def __enter__(self):
            self.f = open(self.path, self.mode)
            return self
    
        def load(self):
            while 1:
                try:
                    yield pickle.load(self.f)
                except EOFError:
                    break
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.f.close()
    
    
    with Mypickle_load('mypickle', 'rb')as f:
        for i in f.load():
            print(i)
        
    View Code

    with 和装饰器的区别:

      都是在一个函数的前后添加功能,但是装饰器装饰一次之后,后面再次使用都是被装饰过的,而with每次使用都得再次调用
    
    
    import time
    class Timer:
        def __enter__(self):
            self.start = time.time()
        def __exit__(self, exc_type, exc_val, exc_tb):
            print(time.time() - self.start)
    
    def func():
        print('wahaha')
        time.sleep(1)
        print('qqxing')
    
    with Timer():
        func()
    
    
    
     
     








  • 相关阅读:
    WPF自定义路由事件
    一文看懂微服务背后的技术演进与应用实践
    云原生消息、事件、流超融合平台——RocketMQ 5.0 初探
    KubeVela 1.1 发布,开启混合环境应用交付新里程碑
    Facebook宕机背后,我们该如何及时发现DNS问题
    Apache Flink 在汽车之家的应用与实践
    新一代容器平台ACK Anywhere,来了
    Serverless 工程实践 | Serverless 应用优化与调试秘诀
    OpenKruise 如何实现应用的可用性防护?
    国家网络安全宣传周:勒索病毒利如刀,上网备好技能包
  • 原文地址:https://www.cnblogs.com/stron/p/10642123.html
Copyright © 2011-2022 走看看