zoukankan      html  css  js  c++  java
  • 面向对象(一)--魔术方法(特殊方法)

    1、__new__方法

    __new__方法:创建对象调用的方法

    __init__方法:初始化对象调用的方法

    一个类如果重写了__new__方法,又没有调用父类的__new__方法创建对象,那__init__方法也不会调用

    class MyTest(object):

    def __init__(self, *args, **kwargs):
    print("这是初始化对象的方法")

    def __new__(cls, *args, **kwargs):
    print("这是new方法,创建对象调用的方法")


    m = MyTest()
    print(m)
    没有调用__init__初始化方法,因为__new__方法没有调用父类的new方法创建对象,故初始化方法不会自动调用

     2、单例模式

    a、什么是单例模式?

    单例模式:一个类只能创建一个对象,这个类就是一个单例模式的类

    b、单例模式的实现

    1)重写__new__方法实现单例模式

    class MyTest(object):
    obj = None # 定义一个类属性,存储创建的对象,如果对象存在,则返回该对象,如果对象不存在则创建对象

    def __init__(self, *args, **kwargs):
    print("这是初始化对象的方法")

    def __new__(cls, *args, **kwargs):
    if not cls.obj:
    cls.obj = super().__new__(cls,*args,**kwargs)
    return cls.obj


    m1 = MyTest()
    m2 = MyTest()
    m3 = MyTest()
    print("{}:内存地址:{}".format(m1, id(m1)))
    print("{}:内存地址:{}".format(m2, id(m2)))
    print("{}:内存地址:{}".format(m3, id(m3)))

    2)使用装饰器实现单例模式

    """
    通过装饰器实现单例模式,只要任意一个类使用该装饰器装饰,那么就会变成一个单例模式的类
    """

    status = {"obj": None} # 定义一个全局变量,存储创建的类


    # 装饰器
    def test_decorator(func):
    def wrapper(*args, **kwargs):
    if not status["obj"]:
    status["obj"] = func(*args, **kwargs)
    return status["obj"]

    return wrapper


    # 被装饰的类
    @test_decorator
    class MyTest(object):

    def __init__(self, *args, **kwargs):
    print("这里是初始化方法")


    m1 = MyTest()
    m2 = MyTest()
    m3 = MyTest()

    print("{}:内存地址:{}".format(m1, id(m1)))
    print("{}:内存地址:{}".format(m2, id(m2)))
    print("{}:内存地址:{}".format(m3, id(m3)))

    c、单例模式的作用

    单例模式的作用:节省内存开销

    例子:

    """
    实现一个类,前五次创建对象,每次都可以返回一个新的对象,第六次开始,每次创建,都随机返回前5哥对象中的一个
    """
    import random


    class CreateObject(object):
    obj_list = []

    def __init__(self):
    pass

    def __new__(cls, *args, **kwargs):
    if len(cls.obj_list) < 5:
    obj = super().__new__(cls, *args, **kwargs)
    cls.obj_list.append(obj)
    return obj
    else:
    return random.choice(cls.obj_list)


    for c in range(10):
    obj = CreateObject()
    print("对象第{}次创建,内存地址:{}".format(c + 1, id(obj)))

    3、上下文管理器---with

    1)迭代器协议是由__iter__方法和__next__方法这两个魔术方法组成的。

    __iter__方法:会在使用内置函数iter(obj),将可迭代对象转换为迭代器时调用。

    __next__方法:会在使用内置函数next(obj),对迭代器进行迭代操作时调用。

    2)为什么with去打开文件进行操作,会自动关闭文件呢?

    因为with启动了文件操作对象的上下文管理器

    3)上下文管理器协议的构成:__enter__方法和__exit__方法

    __enter__方法:启动上下文时会自动调用

    __exit__方法:退出上下文时会自动调用

    4)如果说一个对象实现了__enter__方法和__exit__方法,那么这个对象就实现了上下文管理器协议,就可以使用with这个关键字来开启对象的上下文管理。

    class FileOpen(object):

    def __init__(self, file, mode, encoding):
    self.file = file
    self.mode = mode
    self.encoding = encoding

    def __enter__(self):
    print("-----进入enter方法----")
    self.io = open(self.file, self.mode, encoding=self.encoding)
    return self.io

    def __exit__(self,exc_type, exc_value, exc_traceback):
    print("异常的类型:{}".format(exc_type))
    print("异常的值:{}".format(exc_value))
    print("异常的溯源:{}".format(exc_traceback))
    self.io.close()


    with FileOpen("d06_new.py", "r", "utf-8") as f:
    file_content = f.read()
    # raise AssertionError
    print(file_content)

    4、__call__方法

    1)一切皆对象,其实函数也是对象,函数是可调用的对象

    callable(obj):输出bool,判断对象是否可调用

    name = "123"
    print(callable(name)) # 输出False
    print(callable(str)) # 输出True

    象是否可调用

    2)__call__方法:实现了该方法的对象,该对象是可调用的对象(像调用函数一样调用对象)

    class MyTest(object):

    def __init__(self):
    print("这是初始化方法")

    def __call__(self, *args, **kwargs):
    print("实现了call方法,对象可被调用")


    m = MyTest()
    print(callable(m))
    m() # 对象调用的时候,执行的是__call__()方法

     3)通过类实现装饰器

    class MyDecorator(object):

    def __init__(self, func):
    self.func = func

    def __call__(self, *args, **kwargs):
    print("装饰器扩展功能1")
    res = self.func(*args, **kwargs)
    print("装饰器扩展功能2")
    return res


    @MyDecorator # ==> worker = MyDecorator(worker)
    def worker():
    print("这是Worker功能函数")


    worker()

    5、__str__方法

    1)print输出的内容:是用什么方法来控制的?

    print输输出的其实就是对象的__str__返回的值

    注意点:__str__方法必须要些返回值,返回值的类型只能是字符串

    class MyTest:

    def __init__(self, name, age, gender):
    self.name = name
    self.age = age
    self.gender = gender

    def __str__(self):
    return str(self.name)


    m1 = MyTest("gen", 18, "dalao")
    m2 = MyTest("fei", 18, "pingm")
    print(m1)
    print(m2)

    本文来自博客园,作者:%女王%,转载请注明原文链接:https://www.cnblogs.com/lynne-wu/p/15430864.html

  • 相关阅读:
    使用Nginx搭建http服务器
    (七)Docker搭建httpd集群
    zlib库对文件进行压缩和解压操作
    (一)Apache Thrift 的使用
    (一)select、poll、epoll
    (十三)备忘录模式
    (十二)命令模式
    (十一)迭代器模式
    centos下利用httpd搭建http服务器方法
    shell快捷键
  • 原文地址:https://www.cnblogs.com/lynne-wu/p/15430864.html
Copyright © 2011-2022 走看看