Python基础之魔术方法和描述器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34120459/article/details/88030757

一、魔术方法

1、call :实例直接调用,需要定义__call__方法

  • 未定义__call__方法时:
class Test:
    def __init__(self, num):
        self.num = enumerate

    def __add__(self, other):
        print(self.num)
        print(other.num)
        res = self.num + other.num
        return res

a = Test(8)
a()  #TypeError: 'Test' object is not callable
  • 定义__call__方法后:
class Test:
    def __init__(self, num):
        self.num = enumerate

    def __add__(self, other):
        print(self.num)
        print(other.num)
        res = self.num + other.num
        return res

    def __call__(self):
        print("调用成功")

a = Test(8)
a()    # 调用成功

2、其他魔术方法

class Test:
    """我是一个测试类"""
    def __init__(self, num):
        self.num = enumerate

    def __add__(self, other):
        print(self.num)
        print(other.num)
        res = self.num + other.num
        return res

    def __call__(self):
        print("调用成功")

a = Test(8)
a()    # 调用成功

# 其他魔术方法
print(a.__class__)  # 查看类名<class '__main__.Test'>
print(a.__dict__)   # 查看全部属性{'num': <class 'enumerate'>}
print(a.__doc__)    # 查看类的注释部分,查看对象文档   #我是一个测试类

二、单例模式

1、new 方法:

类只能被实例化一次,也就是说我们的类实例化时,只是变量名不同,但是始终是一个类

  • 使用__new__ 方法前:
class Earth:
    def __init__(self):
        self.name = 'earth'

e = Earth()
print(e, id(e))
f = Earth()
print(f, id(f))
'''
<__main__.Earth object at 0x000001ED22BA7780> 2118001522560
<__main__.Earth object at 0x000001ED22BAF9E8> 2118001555944
e与f内存地址不一样
'''
  • 使用__new__ 方法后:不管实例多少次,都始终是一个对象。即:加了__new__方法后相当于只实例化了一次

注: new 是在__init__前面执行的
是固定的模式,记住就好

class Earth(object):
    def __new__(cls):
        if not hasattr(cls, "instance"):
            cls.instance = super().__new__(cls)
        return cls.instance

    def __init__(self):
        self.name = 'earth'

e = Earth()
print(e, id(e))
f = Earth()
print(f, id(f))

'''
<__main__.Earth object at 0x0000020297084B00> 2210147093248
<__main__.Earth object at 0x0000020297084B00> 2210147093248
使用了__new__方法后,e和f的内存地址相同
'''

2、定制属性访问

即对属性的操作:增删改查

  1. 增、改(无则新增,有则改)

setattr() 或 setattr()

delattr() defattr() 或 del

  1. 查:hasattr,getattr , getattr

3、描述符

函数执行的底层——>魔术方法——>自定义

  • 正常情况下实例化另一个类
class Test:
    pass

class Test1:
    a = Test()  #上一个类的实例化拿来做这一个类的方法,这就是描述符
  • 增删改查方法的扩展
class Test:
    def __get__(self, instance, owner):
        print("__get__")

    def __set__(self, instance, value):
        print("__set__")

    def __delete__(self, instance):
        print("__delete__")


class Test1:
    def __init__(self):
        self.name = 'vae'
    a = Test()  #上一个类的实例化拿来做这一个类的方法,这就是描述符

b = Test1()  # 类的实例化
print(b.name)  # 获取对象属性
b.a            # 会去找__get__方法
b.a = 99       # 会去找__set__方法
del b.a        # 会去找__delete__方法

猜你喜欢

转载自blog.csdn.net/qq_34120459/article/details/88030757