python学习笔记 day27 内置方法

1. __str__() 

先说结论: 内置的类方法和内置函数之间有千丝万缕的关系;

                   当直接打印一个对象print(obj)  或者 print(str(obj)) 或者 %s都是去调用该对象的__str__()方法;

                   如果本类未实现__str__()方法就去调用本类实现的__repr__()方法,找不到再去调父类的__str__()方法;

                   内置的类方法一旦有返回值,必须是str类型的;

class Teacher():
    def __init__(self,name):
        self.name=name
    def __str__(self):
        return "Teacher's obj is %s"%self.name  # 内置的类方法__str__()一旦有返回值,一定是str类型的!
teacher=Teacher('xuanxuan')
print(teacher)  # 直接打印对象其实是调用该对象的__str__()方法;
print(str(teacher)) # str(obj)也是去调用对象obj的__str__()方法
print(">>>%s"%teacher) # %s 也是去调用这个对象的__str__()方法

运行结果:

2. __repr__(): 

先说结论:

             直接打印repr(obj)  即print(repr(obj)) 或者 直接%r 都是去调用对象的内置类方法__repr__();

             内置的类方法__repr__()一旦有返回值一定是字符串类型,否则会报类型错误;

             内置的类方法__repr__()是内置类方法__str__()的备胎,就是当对象去调用__str__()但是本类未实现__str__()时会去调用本类的__repr__()方法,但是反过来不行;

class Teacher():
    def __init__(self,name,salary):
        self.name=name
        self.salarry=salary
    def __repr__(self):
        return str(self.__dict__)  # 在内置类方法__repr__()中调用__dict__()内置方法就是以字典形式打印对象的属性;

teacher=Teacher('xuanxuan',13000)
print(teacher)  # 直接打印对象其实是去调用对象的__str__()方法,但是本类未实现__str__() 就调用__str__()的备胎__repr__()
print(repr(teacher))  # repr(obj)是在调用对象的内置类方法__repr__()
print(">>>%r"%teacher) # %r 也是在调用对象的__repr__()方法

运行结果:

 

 3. __len__():

当调用len()方法时,其实是在调用内置的类方法__len__(),(注意这个内置方法__len__()在object父类中是没有被实现的,也就是如果本类不实现__len__()方法就会报错)

class Classes():
    def __init__(self,name):
        self.name=name
        self.students=[] # 把学生存成一个列表
    def __len__(self):
        return len(self.students)  # 班级这个类中实现的__len__()其实是在计算这个班级的人数(定制类)

s9_python=Classes("python 9期课程班")
s9_python.students.append("璇璇")
s9_python.students.append('嘻嘻')
print(len(s9_python))  # len()方法其实是在调用对象的__len__()方法,但是在这个内置类方法中实现的其实在计算班级对象的students属性(是一个列表)的长度,也即班级中学生人数

运行结果:

4. __del__() 析构函数

其实python解释器内部有一种垃圾回收机制,当这个变量不再被使用时 就会被释放,调用内置类方法__del__() 先执行析构函数中的代码,然后删除这个对象;

析构函数一般是在释放对象前,做一个收尾工作;

执行del(obj)其实是在执行__del__()方法

class A():
    def __del__(self):
        print("被删除之前我被执行啦")
a=A()
del(a)  # 执行del()就是在执行内置类方法__del__()

运行结果:

 

再来看一个例子:

即使没有调用del(a) 由于后面a对象没有在被使用,所以会被释放,执行__del__()析构函数

import time
class A():
    def __del__(self):
        print("被删除之前我被执行啦")
a=A()
time.sleep(3) # 先暂停3秒,然后a不再被使用,就会去调用__del__()方法(即使没有del(a)),把a对象释放掉,所以还是会打印那句话
# del(a)  # 执行del()就是在执行内置类方法__del__()

运行结果:

 

再来看一个有应用场景的,比如我们使用一个对象的属性执行的操作是去打开文件(注意打开文件其实是在执行两个操作,1.在操作系统中打开了一个文件,2. 拿到了文件操作符),当这个对象不再被执行时,就会被释放掉,显然该对象的属性也会被释放,内存中的文件操作符也会被释放,但是文件并不会被关闭,但是对象在被释放时会去执行__del__() 我们就可以在析构函数中执行关闭文件的操作,做一些收尾,执行完之后才会去把这个对象删掉(从内存中释放)

class A():
    def __del__(self):
        self.f.close()  # 在释放对象之前,先执行对象的属性f关闭文件
        print("文件被关闭了")
a=A()
a.f=open("info")

运行结果:

 

5. __call__()

对象() 这种形式就会自动调用__call__()方法

class A:
    def __call__(self):
        print("当对象加上括号时我就被调用执行了~")
a=A()
a()  # 此时会执行__call__()方法

运行结果:

 

posted @ 2018-09-23 11:41  写的BUG代码少  阅读(194)  评论(0编辑  收藏  举报