常见的内置方法、双下方法、魔法方法

内置方法是python的对象内部自带的

并且都比不需要我们自己去调用它

 

 

有了repr或者str在打印对象的时候 就不会显示用户不关心的内存地址了 
增强了用户的体验 在程序开发的过程中 如果我们需要频繁打印对象中的属性,需要从类的外部做复杂的拼接,实际上是一种麻烦
如果这个拼接工作在类的内部已经完成了,打印对象的时候直接就能显示

__str__

打印这个对象的时候自动触发__str__

class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period
    def __str__(self):
        '''打印这个对象的时候 自动触发__str__'''
        '''使用%s进行字符串的拼接的时候 自动触发__str__'''
        return '%s,%s,%s'%(self.name,self.price,self.period)

python = Course('python',25000,'6 months')
print(python)
print('course %s'%python)
print(f'course {python}')
View Code

如果没有实现__str__方法,那么对象打印出来的就只是一串内存地址

 

__repr__

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)

    def __str__(self):
        return self.name

python = Course('python',25000,'6 months')
print(python)
print('course %s'%python)
print(f'course {python}')
print(repr(python))
print('course %r'%python)
View Code
如果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格式化字符串 都会打印出内存地址

打印对象 先走自己的str,如果没有,走父类的,如果除了object之外的所有父类都没有str
再回来,找自己的repr,如果自己没有,再找父类的
repr是str的备胎 和所有的字符串格式化以及直接打印这个对象相关 str(obj),repr(obj)


__new__
构造方法 生产对象的时候用的 - 单例模式

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):
        self.name=name
        if age:
            self.age=age
a1=A('li',55)
a2=A('s',33)
print(a1)
print(a2)
print(a1.age)
View Code

如果不用__new__ 每次实例化的时候也会默认使用__new__ 但是每次实例化开辟的空间不一样

使用 单例模式后  每次实例化 都把信息放在这一个开辟的空间中 内存地址都一样

 

 

__del__ 析构方法  在删除一个对象之前用的 - 归还操作系统资源
import time
class A:
    def __init__(self,path):
        self.f = open(path,'w')
    def __del__(self):
        '''归还一些操作系统的资源的时候使用'''
        '''包括文件\网络\数据库连接'''
        self.f.close()


a = A('userinfo')
time.sleep(1)
View Code

在删除这个之前执行一次里面的内容

大多使用在文件句柄的时候

感觉 好像没有太多其他的用途

 

 

__call__         源码里用比较多 Flask web框架 对象()自动触发__call__中的内容
class A:
    def call(self):
        print('in call')
    def __call__(self, *args, **kwargs):
        print('in __call__')

A()()
obj = A()
obj()
obj.call()
View Code

构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

 

 

 

 

 

with语句 就是和 __enter__,__exit__
在一个函数的前后添加功能
利用使用 装饰器函数中的内容
class MypickleDump:
    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,obj):
        pickle.dump(obj,self.f)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

with MypickleDump('pickle_file') as obj:
    obj.dump({1,2,3,4})

with MypickelLoad('pickle_file') as obj:
   for i in  obj.loaditer():
       print(i)
View Code
class A:
    def __enter__(self):
        print('before')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('after')


with A() as a:
    print('123')
with
class Myfile:
    def __init__(self,path,mode='r',encoding = 'utf-8'):
        self.path = path
        self.mode = mode
        self.encoding = encoding

    def __enter__(self):
        self.f = open(self.path, mode=self.mode, encoding=self.encoding)
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()


with Myfile('file',mode='w') as f:
    f.write('wahaha')
enter和exit

 __enter__中的内容是在执行with之前执行的

__exit__中的内容是在执行with之后执行的


 

 

 
 


 

posted @ 2019-04-06 15:09  老李,向我开炮  阅读(246)  评论(0编辑  收藏  举报