私有化、多态和单例模式

2022-09-20 19:03:18 浏览数 (1)

重新看了一遍发现忘得差不多了,写公众号的好处就是能够让我好好复习。

虽然是把以前学习时的代码直接粘贴过来但还是有好好看的。

代码语言:javascript复制
# 封装:1.私有化 2. 定义公有set和get方法
# 好处:隐藏属性不被外界修改,通过函数才能修改,可以进行赋值内容

class Students:

    def __init__(self, name, age):
        self.__name = name  # (__即为私有化)
        self.__age = age
        self.__score = 59

    def setAge(self, age):  # 筛选
        if age <= 100:
            self.__age = age
        else:
            print("年龄不得超过100")

    def getAge(self):
        return "修改后的年龄是:{}".format(self.__age)

    def __str__(self):
        return "姓名:{} 年龄{} 成绩{}".format(self.__name, self.__age, self.__score)


wo = Students("yft", 20)
wo.__score = 90  # 尝试修改对象的分数
print(wo)  # 姓名:yft 年龄20 成绩59 修改失败,因为score已经私有化,无法修改
wo.setAge(50)
print(wo.getAge())  # 姓名:yft 年龄120 成绩59
print(wo._Students__name)  # 其实还是可以访问的,是伪私有


# 3.property装饰器
class Student:
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    # 装饰器版本
    @property
    def age(self):  # 相当于get
        return self.__age

    @age.setter
    def age(self, age):  # 相当于set
        if 0 < age < 120:
            self.__age = age
        else:
            print("输入的年龄超出范围")

    """  旧版
        def setAge(self, age):
            if 0 < age < 120:
                self.__age = age
            else:
                print("年龄不在正确范围内")
    
        def getAge(self):
            return self.__age
    """

    def __str__(self):
        return "姓名:{} 年龄:{} ".format(self.name, self.__age)


me = Student("yft", 21)
print(me)  # 姓名:yft 年龄:21 
# print(me.__age)  这是无法访问的 会报错
# print(me.getAge())  旧版可以访问到
print(me.age)  # 由于age使用了装饰器,因此不用括号

me.age = 50
print(me)  # 姓名:yft 年龄:50

# 4.多态
# 面向对象三大特点:封装  继承  多态
class Person:
    def __init__(self, name):
        self.name = name

    def feed_pet(self, pet):
        
        """   
        isinstance() 函数来判断一个对象是否是一个已知的类型
        isinstance(object, classinfo)
        object -- 实例对象。
        classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。(考虑子父类)
        """
        
        if isinstance(pet, Pet):
            print("{}喜欢养宠物:{},昵称是{}".format(self.name, pet.role, pet.nickname))
        else:
            print("{}不是宠物,请不要饲养".format(pet.role))


class Pet:
    def __init__(self, nickname, age):
        self.nickname = nickname
        self.age = age

    def show(self):
        print("昵称:{} 年龄:{}".format(self.nickname, self.age))


class Cat(Pet):
    role = "猫"

    def catch_mouse(self):
        print("猫会抓老鼠")


class Dog(Pet):
    role = "狗"

    def guard(self):
        print("狗会看家")


class Tiger:
    role = "老虎"

    def eat(self):
        print("老虎会吃人")


cat = Cat("huahua", 2)
dog = Dog("dahuang", 4)
person = Person("yft")
person.feed_pet(cat)  # yft喜欢养宠物:猫,昵称是huahua
tiger = Tiger()
person.feed_pet(tiger)  # 老虎不是宠物,请不要饲养


# 5.单例模式:只需要一个实例,不需要一直开辟内存

# isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
# 语法:isinstance(object, classinfo)


# ①阻止创建新实例:
class Singleton:
    __isinstance = None  # 默认为没有实例

    def __new__(cls, *args, **kwargs):
        if cls.__isinstance is None:  # 判断是否已有实例
            cls.__isinstance = super().__new__(cls, *args, **kwargs)  # 没有实例则创建一个
            print("--->1")
            return cls.__isinstance  # 实例将是刚刚创建的实例
        else:
            print("---->2")  # 有实例的话就不创建,以阻止创建新实例
            return cls.__isinstance


s = Singleton()  #--->1
s1 = Singleton()  #---->2
s2 = Singleton()  #---->2
print(s)  #<__main__.Singleton object at 0x000001C38E6B87C0>
print(s1)  #<__main__.Singleton object at 0x000001C38E6B87C0>
print(s2)  #<__main__.Singleton object at 0x000001C38E6B87C0>
#因此只有一个实例,无论创建多少个对象调用的都是同一个实例(内存地址都相同)

其实__new__方法我一直不是很懂怎么用,也不知道是用来干嘛的,以后用到了再说吧

0 人点赞