026_内置的类方法(双下线方法)

1, __str__ 和 __repr__

  • obj.__str__  str(obj)    #  %s  str()      直接打印对象 实际上都是走的__str__
  • obj.__repr__ repr(obj)  #  %r  repr()    实际上都是走的__repr__
  • repr 是str的备胎,即调用str时,在命名空间中,如果找不到str方法,但是,有repr方法,就调用repr方法。但str不能做repr的备胎。
  • 都必须返回的是字符串格式。
  • 改变对象的字符串显示 __str__ , __repr__;自定制格式化字符串 __format__
class Teacher:
    def __init__(self,name,salary):
        self.name = name
        self.salary = salary
    def __str__(self):
        return "Teacher's object :%s"%self.name
    def __repr__(self):
        return str(self.__dict__)
    def func(self):
        return 'wahaha'
nezha = Teacher('哪吒',250)

# print(nezha)  # 打印一个对象的时候,就是调用 nezha.__str__
# 所有没有继承的类,默认继承object类,对象中没有就会向object类查找。该方法在object类存在。
# object  里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址。

# print(repr(nezha))   # 执行nezha对象中__repr__()方法
# print('>>> %r'%nezha) # %r执行nezha对象中__repr__()方法

2,item系列

  __getitem__      __setitem__      __delitem__

class Foo:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __getitem__(self, item):
        if hasattr(self,item):
            return self.__dict__[item]

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, key):
        del self.__dict__[key]

f = Foo('egon',38,'男')
print(f['name'])     # f['name']执行__getitem__()方法  #>>>egon

f['hobby'] = '男'    #执行__setitem__()方法
print(f.hobby,f['hobby'])  #>>>男 男

del f.hobby         # object 原生支持  __delattr__,不用调用类里的方法
print(f.__dict__)
# del f['hobby']    # 通过自己实现的,执行__delitem__()方法
# print(f.__dict__)

3,__del__ 

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

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

class A:
    def __del__(self):   # 析构函数: 在删除一个对象之前进行一些收尾工作
        print('执行我了!')
a = A()
del a   # del 既执行了__del__()这个方法,又删除了对象   #>>>执行我了!
  3.2,在python中,会记录你的变量在程序中会用几次并计数,用一次就会将计数减一,当计数为零时就会自动的帮你把这个变量删除,此时也会执行__del__()方法。
class A:
    # 析构函数: 在删除一个对象之前进行一些收尾工作
    def __del__(self):
        print('执行我了!')

lst = []
for i in range(3):
    lst.append(A())  #得到三个变量
    print(i)
import time
time.sleep(3)  # 3秒后程序结束将三个变量删除了 
               #结果打印了三次'执行我了!'

  3.3,使用

    def __del__(self):   # 析构函数: 在删除一个对象之前进行一些收尾工作
        self.f.close()
a = A()
a.f = open()   # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
del a          # a.f 这个拿到的文件操作符就消失在了内存中,但打开的文件并没有关,因此,会先执行__del__()将文件关闭。

4,__call__

class A:
    def __init__(self,name):
        self.name = name
    def __call__(self):
        '''
        打印这个对象中的所有属性
        :return:
        '''
        for k in self.__dict__:
            print(k,self.__dict__[k])
a = A('alex')()  #“对象()”就是调用__call__()方法。

5, __new__  构造方法 : 创建一个对象

  5.1,

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时,先执行了__new__()通过object类创建了一个self对象,在执行__init__()

  5.2,单例模式

  • 一个类 始终 只有 一个 实例
  • 当你第一次实例化这个类的时候 就创建一个实例化的对象
  • 当你之后再来实例化的时候 就用之前创建的对象
class A:
    __instance = False
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __new__(cls, *args, **kwargs):
        if cls.__instance:
            return cls.__instance
        cls.__instance = object.__new__(cls)
        return cls.__instance

egon = A('egg',38)
egon.cloth = '小花袄'
nezha = A('nazha',25)
print(nezha)
print(egon)
print(nezha.name)
print(egon.name)
print(nezha.cloth)

6,__len__

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

    def __len__(self):
        return len(self.__dict__)
a = A()
print(len(a))

7,__hash__

  只要是可哈希的内部一定实现了一个__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','男')

 8,__eq__

class A:
    def __init__(self,name):
        self.name = name

    def __eq__(self, other):
        if self.__dict__ == other.__dict__:  # 不加dict比较的是俩个对象的内存地址。
            return True
        else:
            return False

ob1 = A('egon')
ob2 = A('egg')
print(ob1 == ob2)  # ob1 == ob2 调用__eq__()方法。

9,将部分属性一样的判定为是一个对象,怎么做?

  100 名字 和 性别 年龄不同。

 

class A:
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age

    # def __eq__(self, other):        # 需要加上
    #     if self.name == other.name and self.sex == other.sex:
    #         return True
    #     return False

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

a = A('egg','男',38)
b = A('egg','男',37)
print(set((a,b)))   # unhashable

# set 依赖对象的 __hash__     __eq__

10,命名元组

 

from collections import namedtuple
Card = namedtuple('Card',['rank','suit']) #创建一个以Card命名的元组,和内部元素的命名['rank','suit']
c1 = Card(2,'红心') #创建命名元组对象
print(c1)  #>>>Card(rank=2,suit='红心')
print(c1.suit) #>>>红心 

 

 1 import json
 2 from collections import namedtuple
 3 Card = namedtuple('Card',['rank','suit'])   # rank 牌面的大小 suit牌面的花色
 4 class FranchDeck:
 5     ranks = [str(n) for n in range(2,11)] + list('JQKA')
 6     suits = ['红心','方板','梅花','黑桃']
 7 
 8     def __init__(self):
 9         self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
10                                         for suit in FranchDeck.suits]
11 #此处相当于:for suit in FranchDeck.suits:
12 #        for rank in FranchDeck.ranks:
13 #            Card(rank,suit)
14  
15     def __len__(self):
16         return len(self._cards)
17 
18     def __getitem__(self, item):
19         return self._cards[item]
20 
21 deck = FranchDeck()
22 print(deck[0])  #拿第几张牌
23 from random import choice
24 print(choice(deck))  #调用deck中的__len__()
25 print(choice(deck))
纸牌游戏
 1 class FranchDeck:
 2     ranks = [str(n) for n in range(2,11)] + list('JQKA')
 3     suits = ['红心','方板','梅花','黑桃']
 4 
 5     def __init__(self):
 6         self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
 7                                         for suit in FranchDeck.suits]
 8 
 9     def __len__(self):
10         return len(self._cards)
11 
12     def __getitem__(self, item):
13         return self._cards[item]
14 
15     def __setitem__(self, key, value):
16         self._cards[key] = value
17 
18 deck = FranchDeck()
19 print(deck[0])
20 from random import choice
21 print(choice(deck))
22 print(choice(deck))
23 
24 from random import shuffle
25 shuffle(deck)     #洗牌
26 print(deck[:5]) 
纸牌游戏2
 1 class Person:
 2     def __init__(self,name,age,sex):
 3         self.name = name
 4         self.age = age
 5         self.sex = sex
 6 
 7     def __hash__(self):
 8         return hash(self.name+self.sex)
 9 
10     def __eq__(self, other):
11         if self.name == other.name and self.sex == other.sex:return True
12 
13 
14 p_lst = []
15 for i in range(84):
16     p_lst.append(Person('egon',i,'male'))
17 
18 print(p_lst)
19 print(set(p_lst))
一道面试题

 

posted @ 2019-04-02 17:40  冰羽~zZ  阅读(198)  评论(0编辑  收藏  举报