python--类方法

类方法--双下方法:与内置函数有千丝万缕的关系
一、改变对象的字符串显示__str__,__repr__
obj.__str__     类似str(obj)
obj.__repr__ 类似repr(obj)
    def __init__(self,name):
        self.name=name
    def __str__(self):
        return '她是%s'%self.name        # str 执行的必须是字符串形式
    def __repr__(self):
        return str(self.__dict__)           # repr执行的必须是字符串形式
teacher=Person('teacher')
#第一种调用方法
print(teacher)             #她是teacher   打印一个对象的时候,就是调用a.__str__
print(repr(teacher))     #{'name': 'teacher'}  调用a.__repr__
#第二种调用方法
print('%s'%teacher)     #她是teacher           相当于执行了双下str方法
print('%r'%teacher)     #{'name': 'teacher'}     相当于执行了双下repr方法
#第三种调用方法
print(str(teacher))   #她是teacher   相当于触发了__str__方法
print(repr(teacher))    #{'name': 'teacher'}  相当于触发了__repr__方法
class B:
     def __str__(self):
         return 'str : class B'
     def __repr__(self):
         return 'repr : class B'
b=B()
print('%s'%b)       #str : class B
print('%r'%b)         #repr : class B
练习
"""
object  里有一个__str__内置方法,一旦被调用,就返回调用这个方法对象的内存地址
打印一个对象的时候,就是调用a.__str__
# %s str()  直接打印 实际上都是走的__str__
# %r repr()  实际上都是走的__repr__
print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
repr(),只会找__repr__,如果没有找父类的
"""
class  Person:
    def __init__(self,name):
        self.name=name

    def __repr__(self):
        return str(self.__dict__)
teacher=Person('teacher')
print(teacher)    #{'name': 'teacher'}  这时候没有双下str, 会执行repr方法,
#注释:repr 是str的备胎,但str不能做repr的备胎
#备胎顺序:当类没有继承其他;类,直接继承object祖类则  备胎顺序是:自己的str--->自己的repr--->祖类的str--->祖类的repr
# 当类继承的有其他类的话顺序是:自己的str--->继承类的str--->自己的repr--->继承类的repr--->祖类的str--->祖类的repr

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

__del__    del 对象  就触发了
class A:
    def __del__(self):
        print('执行我啦')
a=A()
del a            #先触发执行了__del__,再删除了a
print(a)         #删除后再打印会报错
__del__
析构函数: 在删除一个对象之前进行一些收尾工作
class B:
    def __del__(self):
        self.f.close()
b=B()
b.f=open('uerseinfo',mode='w',encoding='utf-8')
b.f.write('zxc')        #在文件里写入了zxc
del b                     #b.f 拿到了文件操作符消失在了内存中
三、__call__   对象后面加括号,触发执行。*****
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;
而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class C:
    def __init__(self,name):
        self.name=name
    def __call__(self):
        for k in self.__dict__:
            print(k+':',self.__dict__[k])
c = C('zxc')
a=C('zxc')()        #name: zxc
c()                     #name: zxc
__len__    len()触发执行__len__
class A:
    def __init__(self,name,love):
        self.dog= name
        self.zxc= love

    def __len__(self):
        return len(self.__dict__)
a = A('zxc','pig')
b=A('zxc','dog')
print(a.__dict__)    #{'zxc': 'pig', 'dog': 'zxc'}
print(len(a.__dict__))    #2
__eq__
class D:
    def __init__(self,name,love):
        self.name= name
        self.love= love
    def __eq__(self, other):
        if self.name==other.name:
            return True
        else:
            return False
a=D('zxc','pig')
b=D('zxc','dog')
print(a==b)     #True
__hash__
class A:
    def __init__(self,name,sex):
        self.name = name
        self.sex = sex
    def __hash__(self):
        return hash(self.name+self.sex)
a = A('egon','')
b = A('egon','nv')
print(hash(a))      #-211948449
print(hash(b))      #959576532
__new__  ******
__new__执行先于__init__中的内容 ,并且在实例化的时候自动执行
class New:
    def __init__(self,name):
        self.name=name
        print('in init funcing')
    def __new__(cls, *args, **kwargs):
        print( 'in new funcing')
        return object.__new__( New)
a1=New('zxc')   #in new funcing   最先打印的是__new__方法.再打印in init funcing
print(a1)        #<__main__.New object at 0x01D4EAD0>
print(a1.name)      #zxc
 __new__进阶:23种设计模式中很简单的一个:单例模式,核心思想就是__new__
 单例模式特点:
"""
一个类 始终 只有 一个 实例
当你第一次实例化这个类的时候 就创建一个实例化的对象
当你之后再来实例化的时候 就用之前创建的对象
"""
#注释:一旦有任何修改,都会还是对原来的那个进行重新赋值,并且覆盖之前的实例,从始至终只有一个实例 
class New:
    __flag=False
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex
    def __new__(cls, *args, **kwargs):
        if cls.__flag:
            return cls.__flag
        cls.__flag=object.__new__(cls)
        return cls.__flag
a=New('zxc',38)
print(a.name)   #zxc
b=New('zzy',18)
print(a.name)   #zzy
a.cloth='花裙子'
print(b.cloth)   #花裙子
单例
item系列
__getitem__\__setitem__\__delitem__
class Item:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __getitem__(self, item):
        if hasattr(self,item):
            return self.__dict__[item]
        else:
            return 1
    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        del self.__dict__[key]
i=Item('zxc',38)
两种方法查,其实内部机制一样
print(i.name)        # zxc
print(i['name'])     # zxc
两种方法改,其实内部机制一样
i['name']='zzxxcc'
print(i.name)          ##zzxxcc
i.__dict__['name']='stupd_zxc'
print(i.name)          #stupd_zxc
两种方法删除,其实内部机制一样
del i['name']
print(i['name'])     #1 这种查询方法,虽然找不到,但是不像普通字典那样会报错,这里返回1,
 因为程序里有__getitem__  打印i['name']时候,会先执行__getitem__方法,找item,因为name被删除了,所以就找不到返回'1'
del i.name        #object 原生支持  __delattr__
print(i.name)    #这种删除会报错
#也可以查看一下对象中的内容,看看有没有被删除
print(i.__dict__)      # {'age': 38}
进阶
import json
from collections import namedtuple
Card = namedtuple('Card',['rank','suit'])   # rank 牌面的大小 suit牌面的花色
class FranchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')   # 2-A
    suits = ['红心','方板','梅花','黑桃']
    def __init__(self):
        self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
                                        for suit in FranchDeck.suits]
    def __len__(self):
        return len(self._cards)
    def __getitem__(self, item):
        return self._cards[item]
    def __setitem__(self, key, value):
        self._cards[key] = value
    def __str__(self):
        return json.dumps(self._cards,ensure_ascii=False)
deck = FranchDeck()
print(deck[10])
from random import choice
print(choice(deck))
# print(choice(deck))
from random import shuffle
shuffle(deck)
print(deck[10])
print(deck)
print(deck[:5])
扑克牌
原文地址:https://www.cnblogs.com/zzy-9318/p/8358031.html