del new item hash 单例模式

一.析构方法__del__和构造方法__new_

析构方法: 删除一个对象的时候调用的方法
构造方法: 创建一个对象的
初始化方法: __init__ 给已经创建出来的对象添加属性初始化方法

1.析构方法:

class A:
    def __init__(self,name):
        self.name=name
    def __del__(self):
        print(666)
a=A("alex")
del a
print(a.__dict__)  #NameError: name 'a' is not defined
View Code
删除一个对象的时候,如果内部存在__del__方法,那么在删除一个对象之前先执行__del__方法中的代码
析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
class Foo:
def __del__(self):
print('执行我啦')
f1=Foo() #执行我啦
##没有删-除对象,却仍然执行了__del__函数。原因是解释器在代码全部执行完后会收集没执行的代码,因此会触发
这个函数执行

 

2.__new__创造一个对象。即实例化时为什么能实例化出来一个对象


class A:
    def __init__(self):
        print("执行了init方法")
    def __new__(cls, *args, **kwargs):
        print("执行了new方法")
        return object.__new__(cls)
a=A()
# 执行了new方法 执行了init方法
print(type(a))  #<class '__main__.A'>
print(type(A)) #<class 'type'>
View Code

实例化的实质:先执行__new__方法 创造出一个对象 然后把创造出来的对象传递给__init__方法

二.元类和单例模式

1.元类:type()

类和对象都不是凭空出此现的。对象的产生是类创造的。也有一个类在创建类,这个类叫做元类
type() 所有直接用class创建出来的类的元类都是type
class Preson:pass
print(type(Preson)) #<class 'type'>
class Preson:pass 的完整形式是class Preson(metaclass=type):pass
在接口类和抽象类中不能实例化的原因就是改变了元类
元类 创造 类 所以所有的类的type都是它的元类,默认是type
类 创造 对象 具体创造对象的方法 __new__方法,所有的对象的type都是它对应的类

2.单例模式:一个类可以被多次实例化 但是同一时间在python的内存中,只能有一个实例

class A:
    def __init__(self,name):
        self.name=name
        #print("执行了init")
    def __new__(cls, *args, **kwargs):
        #print("执行了__new__")
        if not hasattr(A,'instance'):
            A.instance=object.__new__(cls)  #instance为A的静态变量
        return A.instance
a=A("alex")
print(a.name)  #alex
b=A("egon")
print(a.name,b.name) #egon egon
View Code

三.item系列

1.__item__系列 操作a['name']这种形式

__getitem__
class A:
    def __init__(self,name):
        self.name=name
        self.age=18
    def __getitem__(self,item):
       return self.__dict__[item]
a=A('alex')
print(a['name'],a['age']) #  alex 18 对应了类中一个方法的语法
先进行初始化,然后执行__getitem__ 在return时不能return self.[item] 对象并没有[item]这种属性
View Code

2.###增加.修改和删除一个属性

class A:
    def __init__(self,name):
        self.name=name
        self.age=18
    def __getitem__(self, item):
        return self.__dict__[item]
    def __setitem__(self, key, value):
       self.__dict__[key]=value
    def __delitem__(self, key):
        del self.__dict__[key]
a=A('alex')
##增加属性
a['sex']='nan'
print(a.__dict__)  #{'name': 'alex', 'age': 18, 'sex': 'nan'}
###查看
print(a.sex)  #nan
print(a["sex"]) #nan
##修改##
a['sex']='不详'
print(a.__dict__)  #{'name': 'alex', 'age': 18, 'sex': '不详'
##删除##
del a['sex']
print(a.__dict__) #{'name': 'alex', 'age': 18}
View Code

四.__call__和__hash__

1.__call__
class A:
def __call__(self,a):
print('执行我了',a)
a = A()('aaa') #等同于a=A() a('aaa')
2.__hash__
不可变的数据类型都可以被hash
class A:
def __hash__(self):
return 1
a = A()
b = A()
print(hash(a))
print(hash(b))
hash(obj)函数,obj对象对应的类必然内部实现了__hash__方法
hash的结果就是__hash__方法的返回值
且在一次成的执行过程中是不会发生变化的
且要想作为字典的key或者作为集合的元素,这个对象对应的类必须实现__hash__方法

面试题


有一个类,对应这个类产生了100个对象
每个对象有三个属性 : 姓名 年龄 性别
请对这一百个对象进行去重,如果姓名和性别相同,即便年龄不同也是相同的对象
'''
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def __hash__(self):
        return hash('%s%s'%(self.name,self.sex))
    def __eq__(self, other):
        if self.name == other.name and  \
            self.sex == other.sex:
            return True
p_lst = []
for i in range(100):
    p_lst.append(Person('egon',i,'male'))  #print(Person('egon',18,'male'))显示对象的地址
print(p_lst)
print(set(p_lst)) # 报错不可hash 完成了__hash__
View Code

 

 
 
 
 
posted @ 2018-03-13 20:23  JERD  阅读(223)  评论(0编辑  收藏  举报