笔记:python基础之面向对象进阶——内置方法

内置方法__str__,__repr__,__del__,__call__
内置的类方法 和 内置的函数之间有着千丝万缕的联系
也称为双下方法

obj.__str__ /str(obj):object里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址;在类中有设置,打印一个实例化对象的时候,就是调用对象名.__str__

print(obj)/%s/str(obj):内部实际调用了__str__
%r/repr():内部实际调用了__repr__(repr是str的备胎,如无__str__则调用__repr__,反过来则不行)

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)  # 打印一个对象的时候,就是调用a.__str__
print(repr(nezha))
print('>>> %r'%nezha)
#输出:
Teacher's object :哪吒
{'name': '哪吒', 'salary': 250}
>>> {'name': '哪吒', 'salary': 250}

str与rpr的关系

  • print(obj)/’%s’%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串。
  • 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
  • repr(),只会找__repr__,如果没有找父类的

内置的方法有很多
不一定全都在object中

class Classes:
    def __init__(self,name):
        self.name = name
        self.student = []
    def __len__(self):
        return len(self.student)
    def __str__(self):
        return 'classes'
s= Classes('python')
s.student.append('jack')
s.student.append('david')
print(len(s))
print(s)
#输出:
2
classes

__del__方法

# class A:
#     def __del__(self):   # 析构函数: 在删除一个对象之前进行一些收尾工作
#         self.f.close()
# a = A()
# a.f = open()   # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
# del a          # a.f 拿到了的文件操作符消失在了内存中
# del a   # del 既执行了这个方法,又删除了变量
# 引用计数

__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')()→输出:name alex

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):#增加属性→对象['']=value
        self.__dict__[key] = value#删除→del 对象['']
    def __delitem__(self, key):
        del self.__dict__[key]
f = Foo('egon',38,'男')
print(f['name'])
f['hobby'] = '男'
print(f.hobby,f['hobby'])
#del f.hobby      # object 原生支持  __delattr__
del f['hobby']   # 通过自己实现的
print(f.__dict__)
#输出:
egon
男 男
{'name': 'egon', 'sex': '男', 'age': 38}

__init__ :初始化方法,参数self是new构造出来的。
__new__ : 构造方法 : 创建一个对象
先执行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)

# a1 = A()
# a2 = A()
# a3 = A()
# print(a1)
# print(a2)
# print(a3)
# print(a.x)
#一个类始终只有一个实例

每次创建对象,都把前一对象的信息覆盖。

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)

#输出:
<__main__.A object at 0x000000000526DDD8>
<__main__.A object at 0x000000000526DDD8>
nazha
nazha
小花袄

__eq__方法: 当比较两对象时,正常情况下比较的是内存地址,但在类中定义:def __eq__():之后可控制比较结果的输出,只要一比较两个对象,如ob1==ob2,就会自动触发__eq__方法。

class A:
    def __init__(self,name):
        self.name = name
    def __eq__(self, other):
        if self.__dict__ == other.__dict__:
            return True
        else:
            return False
ob1 = A('egon')
ob2 = A('egg')
print(ob1 == ob2)

#输出:
False

__hash__方法:只要是可哈希的,内部都调用了__hash__方法,比较两对象的哈希值是,正常情况下比较的是内存地址,在类中定义def __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))
print(hash(b))

应用举例:
构建扑克牌的类。

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])
print('=======')
from random import choice
print(choice(deck))
print(choice(deck))
print('=======')
from random import shuffle
shuffle(deck)
print(deck[10])
#print(deck)
print(deck[:5])

#输出:
Card(rank='4', suit='梅花')
=======
Card(rank='10', suit='方板')
Card(rank='4', suit='方板')
=======
Card(rank='3', suit='红心')
[Card(rank='Q', suit='红心'), Card(rank='K', suit='梅花'), Card(rank='Q', suit='梅花'), Card(rank='10', suit='方板'), Card(rank='K', suit='红心')]

内置函数 内置的模块 内置的基础类型 < — >类的内置方法
== < — > __eq__
len() < — > __len__

名字 和 性别 年龄不同
set集合(筛选重复值):set 依赖对象的 hash eq
有eq函数时,内存地址只有一个;
无eq函数时,内存地址有两个。

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值