面向对象进阶

本文深入探讨了单例模式的实现原理,利用Python的__new__方法确保类的唯一实例。同时,讲解了如何重载==操作符和自定义哈希方法,以及Python中__getitem__、__setitem__、__str__等特殊方法的应用,通过实例展示了这些特性的使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

  面向对象进阶(1)

# 设计模式
    # 23种
    # 单例模式
        # 限制一个类在程序开始到结束始终只有一个对象实例
        # 当你第一次实例化这个类的时候,就创建一个实例化的对象,但是当你之后再实例化的时候还是就用之前创建的对象


# 实现单例模式,主要用__new__方法,因为__new__是实例化时被第一个运行的函数
class A:
    __instance = False

    def __init__(self, name, age):  # 为__new__创建的对象进行增加属性,还是觉得相当于构造函数
        self.name = name
        self.age = age

    def __new__(cls, *args, **kwargs):  # 创造对应类的对象方法,实例化时最先调用的
        if cls.__instance:  # 如果为True,表示创建过对象,则直接返回这个对象,不在创建
            return cls.__instance
        else:
            cls.__instance = object.__new__(cls)  # 创建一个cls类的对象,返回给cls.__instance
            return cls.__instance   # 返回cls.__instance对象

egon = A('egg', 25)
nezha = A('nazha', 21)
print(egon) # <__main__.A object at 0x00000238A56F30B8>
print(nezha)    # <__main__.A object at 0x00000238A56F30B8>
print(nezha.name)   # nazha
print(egon.name)    # nazha



# __eq__   ==的操作符重载函数,不实现默认比较的是内存地址
class A:
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):    # 当不实现这个内置方法时,obj1和obj2比较的是内存地址,实现后相当于重载了==,根据自己的情况去写。==的操作符重载函数
        #return self == other   # 比较的是内存地址
        if self.name == other.name:
            return True
        else:
            return False

obj1 = A('egg')
obj2 = A('egg')

print(obj1)
print(obj2)
print(obj1 == obj2)


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

a = A('why')
b = A('why')
print(hash(a))  # 默认是根据a对象的内存地址进行哈希的
print(hash(b))

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

    def __hash__(self): # 如果想要hash一个对象,不想根据对象的内存地址去进行hash,则需要自己去实现一个内置的__hash__方法,不实现,hash对象时默认是对对象的内存地址进行hash
        return hash(self.name + self.sex)

a = A('why', '12')
b = A('why', '12')
print(hash(a))  # 默认是根据a对象的内存地址进行哈希的
print(hash(b))



# 纸牌游戏例子
from collections import namedtuple
import json
Card = namedtuple('Card', ['rank', 'suit'])
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):
        return len(self.__cards)

    def __getitem__(self, item):
        return self.__cards[item]

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

    def __str__(self):  # 必须返回str类型的,所以需要序列化
        return json.dumps(self.__cards, ensure_ascii=False) # json序列化(转为字符串),返回

deck = FranchDeck()
print(deck[0])  # 得益于对象实现的__getitem__方法

from random import choice   # 抽取,随机从对象中抽取,抽取的对象必须有len方法,依赖__len__方法,所抽取的对象必须有__len__方法
print(choice(deck)) # 抽牌

from random import shuffle  # 打乱顺序,依赖于__setitem__方法,所打乱的对象必须有__setitem__方法
shuffle(deck)   # 洗牌

print(deck) # 得益于__str__,将所有的牌打印了出来,打印self.__cards列表
print(deck[:5])

# set集合 依赖对象的 hash和eq, set(对象时),目的为了去重,依赖于hash和eq,需重新实现eq和hash

 

转载于:https://www.cnblogs.com/whylinux/p/9740099.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值