• python_单例模式实现、部分魔术方法介绍(callable、__init__、__new__、__str__、__add__、__enter__、__exit__)、鸭子类型简介


    一。单例模式

    1)单例模式概念:只有一个实例

    2)实现方法:

        (1)import

        (2)单例模式

        (3)装饰器

    3)单例模式的原理:通过__new__(这个内置方法很懵逼吧,因为我们一般写代码用不到确实是存在并自己运行的,不要急下面介绍)实现单例模式:

      __new__ 的关系:
      __new__ 会先创建对象并分配内存

    4)单例模式的实现过程:

    class Person(object):
    obj = 2
    def __init__(self):
    pass

    def __new__(cls, *args, **kwargs):
    """如果对象已经创建,就直接把创建好的对象返回
    如果对象没有创建,就创建对象,并返回"""
    if not cls.obj:
    cls.obj = super().__new__(cls) #分配内存
    return cls.obj
    if __name__ == '__main__':
    name_1 = Person()
    name_2 = Person()
    print(name_1 is name_2)
    print(id(name_1), id(name_2))

    运行结果(可以看出,name_1 与 name_2 虽然他们两个都赋值了 类Person 但是他们是一样的,也就是只有一个实例;当然这里我们就疑问类,是不是单例对我有什么影响那。设想下如果我们

    调用的实例 他们都是可以变化的在你频繁调用该实例的时候对你有什么影响那?):

    二。魔术方法:

    1)callable:内置函数,判断对象能不能加括号运行

    类方法加__call__使其可以加括号运行,具体作用请参考上一篇文章“python_...装饰器”

    举栗:

      

    def add(x, y):
    return x + y


    class MyClass(object):
    pass

    class MyClass2(object):
    def __call__(self, *args, **kwargs):
    pass
    if __name__ == '__main__':
    print(callable(add)) # 函数方法是可以加括号运行的,返回结果为:ture
    print(callable(MyClass())) #类是不可以加括号运行的,返回结果为:fals

    print(callable(MyClass2())) #想要使类加括号运行需要添加__call__内置方法:ture

    2)__init__ 与 __new__

    两者之间的关系:

    __new__ 会先创建对象并分配内存,然后创建之后会返回一个对象(也就是self),然后会传给__init__,
    然后,__init__参数会绑定到new创建的对象上(也就是self);如果new有值会重写init内容
    #方式一:
    class Person(object):
    def __init__(self, name):
    self.name = name
    print('这里是__init__,会初始化对象的值')

    def __new__(cls, *args, **kwargs):
    print('这里是__new__会先创建对象并分配内存')
    self = super().__new__(cls)
    # 如果不写return返回的是none
    return self
    if __name__ == '__main__':
    mingzi = Person('名字')

    运行结果(运行结果可以看出来,__new__先创建对象并分配内存后返回self,然后__init__初始化对象的值):

    #方式二,这里的__add__不明白没关系,在本章魔术方法:4)有专门解释:
    class Myclass(object):
    def __init__(self, value):
    self.value = value

    def __add__(self, other):
    # self:第一个对象
    # other:第二个对象
    return self.value + other.value


    if __name__ == '__main__':
    # 巩固类与对象调用过程,前两行等价与 obj1 = Myclass(1)
    obj3 = object.__new__(Myclass) # 创建对象,object是超级类
    obj3.__init__(3) # 初始化对象
    print(obj3.value) # 获取对象的属性value

    运行结果:

    3)__str__:自定义对象输出的样式,输出的需要是字符串

    #查看list中是否有__str__内置方法
    print(hasattr(list, "__str__")) # True
    print([1, 2, 3])


    class MyList(list):
    def __str__(self): #__str__ 就是print对象时,对象输出的样子;自定义对象输出的样子,输出时需要是字符串
    result = ''
    for value in self:
    result += str(value)
    return f"{result}"


    if __name__ == '__main__':
    print(MyList([1, 2, 3, 4]))

    运行结果:

    4)__add__:对两个同类型的对象进行 + 操作,会执行对象的 __add__ 方法。(若对象中没有__add__内置方法的定义在执行相加时会报错,这里不展示报错结果)

      

    class Myclass(object):
    def __init__(self,value):
    self.value = value

    def __add__(self, other):
    #self:第一个对象
    #other:第二个对象
    return self.value + other.value


    if __name__ == '__main__':
    obj1 = Myclass(1)
    obj2 = Myclass(2)
    print(obj1 + obj2) # ==> print(obj1.__add__(obj2))
    print(obj1.__add__(obj2))

    运行结果:

    5)__enter__ 与 __exit__:输入和退出内置方法,会先执行__enter__方法然后执行__exit__方法。这两个方法通常会用作 上下文管理器使用,比较常见的有 with 、open方法,

    被with包裹的代码在执行前先执行__enter__方法,代码结束后会执行__exit__方法

      

    #1.自定义__enter__ 与 __exit__方法,并使用with
    class Myclass(object):

    def __enter__(self):
    print("enter...")

    def __exit__(self, exc_type, exc_val, exc_tb):
    print("exit...")

      

    if __name__ == '__main__':
    # 1.自定义__enter__、__exit__方法
    obj = Myclass()
    with obj as o:
    print("~~~~~~~")

    运行结果:

    # 2.open
    # # 典型的支持上下文管理器的方法:open 方法返回一个文件对象,文件对象支持上下文管理协议
    f = open("temp.txt", 'w')
    print(hasattr(f, '__enter__')) #返回:True
    print(hasattr(f, '__exit__')) #返回:True
    f.close()

    三。鸭子类型:是动态中的风格,只在意你在方法不在意你的对象。使用场景(之一):发送消息

    #实现1,不在意对象是否是Cat 或者是 Dog,只要方法相同即可,在方法f中调用此方法
    class Cat(object):
    def say(self):
    print("maio~~~~")

    class Dog(object):
    def say(self):
    print("wang~~~")


    def f(obj):
    """obj 只要是用say方法的对象就行"""
    obj.say()

    #实现2
    class Cat1(object):
    def listing(self):
    print("maio~~~~1")

    class Dog1(object):
    def listing(self):
    print("wang~~~1")


    def f1(obj):
    """obj 只要是用listing方法的对象就行"""
    obj.listing()

    if __name__ == '__main__':
    #实现1
    f(Cat())
    f(Dog())

    #实现2
    f1(Cat1())
    f1(Dog1())

    运行结果:

    爱折腾的小测试
  • 相关阅读:
    【Vue】二维码生成
    【微信运动】刷步数作弊办法
    webpack创建ts+vue3项目
    最新版vue脚手架搭建项目之如何关闭eslint代码检查
    vue3中如何设置按钮权限控制(如何注册自定义组件)
    科研密匙,ip查询
    vue用vif销毁组件 无效
    面试题
    MySql设置了主键,但是自增跳跃性增长问题
    红黑树的实际意义
  • 原文地址:https://www.cnblogs.com/newsss/p/14616711.html
Copyright © 2020-2023  润新知