双下方法(魔法方法)

目录

1. __new__   <  类名加()   触发   >

利用 __new__ 写单例模式:

2. __len__     <   len()  触发   >

3. __hash__    <   hash()  触发   >

4. __str__    <   print(对象名)  触发   >

5. __item__  系列

 1 )__getitem__

 2)__setitem__

 3)__delitem__

 4)__delattr__

5. __repr__    <   print(repr(对象名))  触发   >   

6. __call__    <  对象名()   或者 类名()()  触发   >

7. __eq__    <  对象名 == 对象名    会触发   >

8. __del__  < del 变量名 或者 类 或者 方法名时会执行>     不需要去程序员去关心,垃圾处理机制帮助处理

9. __enter__     和  __exit__

自定义文件管理器


提示:不知不觉就触发了这些方法, 但是,双下方法主要是python源码程序员使用的,我们在开发中尽量不要使用双下方法,但是深入研究双下方法,更有益于我们阅读源码。

 

1. __new__   <  类名加()   触发   >

  • __new__ 是真正的构造函数  ,他会将类对象 传到 cls 
  • 执行完后 会创造一个 真正的类空间,并赋值公共属性
  • 当 类名加括号时, 会率先执行 __new__ 方法,构造出来一个  类 
  • 然后才 通过__init__ 方法 在真正的实例化出来一个 具体的实例
class A:
    def __init__(self):
        self.x = 1
        print('in init function')
    def __new__(cls, *args, **kwargs):
        print('in new function')
        return object.__new__(A, *args, **kwargs)

a = A()            #此时就会先去 执行 __new__ 再去执行 __init__
print(a.x)

利用 __new__ 写单例模式:

class A:
    __msg = None    #用来记录对象信息

    def __new__(cls,*args,**kwargs):
        if not cls.__msg:   #当 __msg 为 None 时,证明是第一次创建对象空间
            cls__msg = super().__new__(cls)    #调用父类的__new__方法。 记得参数为 cls(类本身)
        return cls.__msg    #将对象空间返回
    
    def __init__(self):pass

a = A()
a1 = A()
print(a)
print(a1)        #两个地址相同

2. __len__     <   len()  触发   >

len()   方法其实执行的是 __len__   当类中没有__len__ 这个方法时,使用len()就会报错

class B:
    def __len__(self):
        print(666)

b = B()
len(b)             # len 一个对象就会触发 __len__方法。

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)        #返回一个 数值型(int...)
a = A()
print(len(a))     # 返回的是 对象的属性个数

3. __hash__    <   hash()  触发   >

hash()   方法其实执行的是 __hash__   当类中没有__hash__ 这个方法时,会去执行父类的 __hash__

不可哈希的 数据类型中  __hash__ = None

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __hash__(self):
        return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))

4. __str__    <   print(对象名)  触发   >

其实 print(对象名)   执行的是 __str__ 方法

如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。

class A:
    def __init__(self):
        pass
    def __str__(self):
        return '太白'
a = A()    
print(a)                #  '太白'
print('%s' % a)        #  '太白'

5. __item__  系列

    1 )__getitem__

class A:
    def __getitem__(self,item):
        print("执行我了",item)        #item == 阿瑟东
        return "1111"

a = A()
print(a["阿瑟东"])                # 打印出 "1111"

    2)__setitem__

class A:
    def __setitem__(self,key,value):
       print(key,value)            # k  ,  v

a = A()
a["k"] = "v"        #触发 __setitem__
 

    1 和 2 一起连用:

class B:
    
    def __getitem__(self,item):
        return getattr(self,item)        #其实返回的就是 self.item 即 self.key的值

    def __setitem__(self,key,value):
        setattr(self,key,value)        #其实是  self.key = value

b = B()
b["k1"] = "v1"
print(b["k1"])

    3)__delitem__

class B:
    
    def __delitem__(self,key):
        delattr(self,key)        #手动删除

       
    def __setitem__(self,key,value):
        setattr(self,key,value)        #其实是  self.key = value

b = B()
b["k1"] = "v1"
del b["k1"]        #触发 __delitem__ 方法

    4)__delattr__

例子二:

class B:
    def __init__(self,lst):
        self.lst = lst
    
    def __getitem__(self,item):
        return self.lst[item]

    def __setitem__(self,key,value):
        self.lst[key] = value
    
    def __delitem__(self,key):
        self.lst.pop(key)

b = B([1,2,3,4])
print(b[1])        # 2
b[2] = "as"
print(b.lst)        # [1,2,"as",4]
del b[2]
print(b.lst)        # [1,2,4]

例子一:

class Foo:
    def __init__(self,name,key,value):
        self.name=name

        self.dict = {}
        self.dict[key] = value

    def __getitem__(self, key):
        print("1313",self.dict[key])
        # return self.dict[key]

    def __setitem__(self, key, value):
        self.__dict__[key]=value
        print(key,"创建新的键值对")

    def __delitem__(self, key):
        print('del obj[',key,']时,我执行')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.',item,'时,我执行')
        self.__dict__.pop(item)

f1 = Foo("sb","A","1")
f1["A"]           #会去执行  __getitem__ 方法
f1['age']=18            #会去执行  __setitem__ 方法
f1['age']=112           #修改也会去执行 __setitem__ 方法
f1['age1']=250           #修改也会去执行 __setitem__ 方法
del f1.age1             #会去执行  __delattr__ 方法
del f1['age']           #会去执行  __delitem__ 方法
f1['name']='alex'       #会去执行  __setitem__ 方法
print(f1.__dict__)

6. __repr__    <   print(repr(对象名))  触发   >   

简称:原形毕露

如果一个类中定义了__repr__方法,那么在repr(对象) 时,默认输出该方法的返回值。

class A:
    def __init__(self):
        pass
    def __repr__(self):
        return '太白'
a = A()
print(repr(a))        # '太白'    输出结果带引号
print('%r'%a)          # '太白'    输出结果带引号

7. __call__    <  对象名()   或者 类名()()  触发   >

class Foo:
    def __init__(self):
        pass    
    def __call__(self, *args, **kwargs):
        print('__call__')

obj = Foo() # 执行 __init__
obj()       # 执行 __call__

8. __eq__    <  对象名 == 对象名    会触发   >

class A:
    def __init__(self):
        self.a = 1
        self.b = 2
    def __eq__(self,obj):
        if  self.a == obj.a and self.b == obj.b:
            return True
a = A()
b = A()
print(a == b)

9. __del__  < del 变量名 或者 类 或者 方法名时会执行>     不需要去程序员去关心,垃圾处理机制帮助处理

析构方法,当对象在内存中被释放时,自动触发执行。

class A:
    
    def __del__(self):
        #析构方法 del A的对象会自动触发这个方法   先执行这个方法,然后才真正将其从内存中删掉
        print("执行我了")

a = A()
del a
print(a)

其对象借用了操作系统的资源,还要通过析构方法归还回去:文件资源,网络资源

#一般使用情况
class A:
    def __init__(self,file_path)
        self.f = open(file_path)

    
    def __del__(self):
        self.f.close()        #用来归还 占用的资源

a = A("文件")

10. __enter__     和  __exit__

class A:
    
    def __init__(self, text):
        self.text = text
    
    def __enter__(self):  # 开启上下文管理器对象时触发此方法
        self.text = self.text + '您来啦'
        return self  # 将实例化的对象返回f1
    
    def __exit__(self, exc_type, exc_val, exc_tb):  # 执行完上下文管理器对象f1时触发此方法
        self.text = self.text + '这就走啦'
        
with A('大爷') as f1:          #触发 __enter__
    print(f1.text)            #执行完毕后触发 #触发 __exit__
print(f1.text)

有他们可以这样操作

自定义文件管理器

class Diycontextor:
    def __init__(self,name,mode):
        self.name = name
        self.mode = mode
 
    def __enter__(self):
        print "Hi enter here!!"
        self.filehander = open(self.name,self.mode)
        return self.filehander
 
    def __exit__(self,*para):
        print "Hi exit here"
        self.filehander.close()        #关闭文件流
 
 
with Diycontextor('py_ana.py','r') as f:
    for i in f:
        print i

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值