Python 5 面向对象进阶

一、反射

反射就是用字符串类型的变量名来访问这个变量。

hasattr,getattr,setattr,delattr

 

二、内置方法(魔术方法)

1、__new__方法(构造方法)

在实例化对象时,第一步就是为对象开辟一块新的内存空间,然后将这个空间传给init方法。开辟空间就是new方法做的事。

# 示例:利用new方法构造一个单例模式
class Single:
    __ISINSTANCE = None
    def __new__(cls, *args, **kwargs):
        if not cls.__ISINSTANCE:  # 第一次实例化
            cls.__ISINSTANCE == object.__new__()
        return cls.__ISINSTANCE

    def __init__(self):
        pass

2、__del__析构方法

在两种情况下生效,一是使用del,二是python的垃圾回收机制生效时触发。一般析构方法用来释放一些在创建对象时借用的系统资源,如文件资源、网络资源等,这些资源是操作系统层面的,python不能直接控制,所以python的垃圾回收也不会顾及这些,需要析构方法来帮助回收。

class File:
    def __init__(self, file_path):
        self.f = open(file_path)
    def __del__(self):
        self.f.close()  # 当程序执行完后会自动执行。

3、__call__方法,通过对象( )调用

4、__len__方法,len( )函数实际上就是在执行__len__方法

5、__next__,__iter__

6、__str__和__repr__

__repr__会把字符串的两个引号也显示出来。当str和repr两个方法都有时,优先使用str方法,当str方法没有时,str()和print都会使用repr方法。

7、__hash__

hash(obj)方法中的obj对象必须定义了__hash__方法。

hash是一种算法,能把一个值经过一系列计算,转化成一个数字,不同的值转化的数字不同,在一次操作中,相同的值转化成相同的数字。

字典的寻址和集合的去重就是利用了hash算法。

字典寻址是先将字典的键保存在任意位置,再hash这个键,得到的数字就是值的内存地址,所以当需要找一个键对应的值的时候,直接hash这个键就能得到内存地址,速度很快。

集合在保存数据时对每个值进行hash,得到内存地址,将这个值保存在这里,如果后面的值hash得到了相同的结果,再判断两个值是否相等,如果想等就去重,所以集合保存的就是每个值的内存地址,没有重复的。

8、__eq__

==和__eq__方法有关,当进行==比较时就是在执行eq方法,可以定义两个对象相等的条件。

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        if self.name == other.name and self.age == other.age:
            return True  # 如果两个对象的name和age都相等就认为这两个对象相等

a1 = Student("a", 1)
a2 = Student("a", 1)
print(a1==a2)  # 得到True

 

三、抽象类和接口类

都是用来规范子类中必须实现的方法。无论如何这两种都不能被实例化。

python中有原生实现抽象类的方法,但是没有原生实现接口类的方法。

在java中只支持单继承,遵循单继承原则的基类就是抽象类,抽象类中的方法都可以实现。但是java不支持多继承,如果想实现多继承需要使用interface创建接口类,接口类中的方法不能被实现智能pass,接口类都是用来被子类多个继承的。

from abc import ABC, abstractmethod
class Te(ABC):
    @abstractmethod
    def test(self):
        pass

 

四、其他

1、__slots__类属性

如果定义了__slots__类属性,那么这个类在实例化时,就会选择用和__slots__同类型的可迭代对象(如元组)来保存实例变量,而不是使用需要占用很多内存的字典__dict__属性。这样可以节约很多内存,尤其是在实例非常多的时候,避免无谓的内存占用。

注意:__slots__属性不会被子类继承,所以子类必须重新定义。

class Test:
    __slots__ = ("m", "k")  # 只能有m和k两个实例变量

 

 

 

posted @ 2019-05-11 00:34  不可思议的猪  阅读(165)  评论(0编辑  收藏  举报