day28 python学习面向对象进阶 带有双下方法的

_str__和__repr__

改变对象的字符串显示__str__,__repr__

#str 和 repr
# class A:
#     # pass
#     def __str__(self):
#         return 'A的对象'

    # def __repr__(self):
    #     return 'repr: A的对象'


# a = A()
# print(a)  #本质调用的是__str__,如果没实现,就调用__repr__, 再找不到,用object父类的
# print(a.__str__())  #str却不能给repr做备胎
# print(a.__repr__()) #repr是str的备胎
# 打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值
# print(str(a))
# print(repr(a))
# print('%s'%a)  #实际上就是在调用他的__str__方法
# print('%r'%a)#  实际上就是在调用他的__repr__方法

自定制格式化字符串__format__

#_*_coding:utf-8_*_

format_dict={
    'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
    'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
    'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type

    def __repr__(self):
        return 'School(%s,%s)' %(self.name,self.addr)
    def __str__(self):
        return '(%s,%s)' %(self.name,self.addr)

    def __format__(self, format_spec):
        # if format_spec
        if not format_spec or format_spec not in format_dict:
            format_spec='nat'
        fmt=format_dict[format_spec]
        return fmt.format(obj=self)

s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)

'''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))

__del__

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

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

class A:
#     def __del__(self):
#         '''
#         析构方法
#         这个方法只有在执行del A类的对象的时候才被触发
#         且先执行代码中的内容,再删除对象
#         如果我删除了这个对象,它跟着还有一些其他的附属的内容也没有用了
#         我们就可以在这个方法中回收掉
#         '''
#         print('执行我啦!')
#         self.b.close()
# f = open('file','w')
# a = A()
# a.b = f
# del a
# print(a)

item系列

__getitem__\__setitem__\__delitem__

class Foo:
    def __init__(self,name):
        self.name=name
    def __getitem__(self, item):
        if item == 1:
            print('hahaha')
        # print(self.__dict__[item])
    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.key时,我执行')
        self.__dict__.pop(item)

f1 = Foo('sb')
#访问属性的方式变了
#对象名.属性
# f1=Foo('sb')
# f1['age']=18  #给f1添加一个属性
# del f1['age']  #删除属性
# # f1.name
# print(f1['name'])
#
# f1.__dict__['age'] = 18
# f1['age1']=19
# del f1.age1   #删除属性
#
# f1['name']='alex'
# print(f1.__dict__)

#关于item : 对象访问 如果是 对象名[],是因为内部实现了item系列的方法

__new__

实例化对象:

  1.创造一个裸的对象,  __new__方法(类中没有就去object中去找)

  2.用  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()
print(a.x)
class Singleton:
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance

one = Singleton()
two = Singleton()

two.a = 3
print(one.a)
# 3
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
# 29097904
print(id(two))
# 29097904
print(one == two)
# True
print(one is two)

单例模式

__call__

对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class Foo:

    def __init__(self):
        pass
    
    def __call__(self, *args, **kwargs):

        print('__call__')


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

_hash__

    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))  #当在外部使用hash()这种方法实际上就是在内部调用  __hash__这个方法
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)  #在外部执行==实际上就是在内部调用 __eq__方法

__len__

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

    def __len__(self):
        return len(self.__dict__)  #返回的是对象自身的长度
a = A()
print(len(a))
rom collections import namedtuple
Card=namedtuple('Card',['ranks','suits'])  #可命名元祖
class FranchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')#列表表达式
    suits = ['红心','方板','梅花','黑桃']

    def __init__(self):
        self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
                                        for suit in FranchDeck.suits]

    def __len__(self):  #这个也必须有,否者不能choice
        return len(self._cards)  

    def __getitem__(self, item):# 这里设置可以通过对象名加括号的形式访问
        return self._cards[item]

deck = FranchDeck()
print(deck._cards)
print(deck[50])  # 调用了上述的__getitem__方法 
from random import choice
print(choice(deck))
print(choice(deck))
洗牌
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __hash__(self):
        return hash(self.name+self.sex)

    def __eq__(self, other):
        if self.name == other.name and self.sex == other.sex:return True
           #other.name

p_lst = []
for i in range(84):
    p_lst.append(Person('egon',i,'male'))

print(p_lst)
print(set(p_lst))

 

posted on 2017-11-27 21:51  王大拿  阅读(200)  评论(0)    收藏  举报

导航