python类中的双下划线方法

  __getitem__,__setitem__和__delitem__

  实现了对象属性的字典化操作。

class Person:
    def __init__(self, name, age, hobby):
        self.name = name
        self.age = age
        self.hobby = hobby

    def __getitem__(self, item):
        if hasattr(self, item):
            return self.__dict__[item]

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

    def __delitem__(self, key):
        del self.__dict__[key]


zxc = Person('zxc', 26, 'read')
print(zxc.name)   # zxc 对象原生查看属性的方法
print(zxc['name'])  # zxc 通过getitem实现的查看方法
zxc['name'] = 'zzy'  # 通过setitem实现修改
zxc['weight'] = 70   # 通过setitem实现增加
print(zxc.__dict__)  # {'weight': 70, 'name': 'zzy', 'hobby': 'read', 'age': 26}
del zxc['hobby']  # 通过delitem实现删除
print(zxc.__dict__)  # {'name': 'zzy', 'weight': 70, 'age': 26}

  __new__构造方法:创建一个对象

  实例化要用到__new__方法

class Foo:
    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        return '创建一个对象'


obj = Foo('zxc')  # 当实例化一个对象的时候,调用的就是__new__方法。
print(obj)  # 打印:创建一个对象
class Foo:
    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        return object.__new__(Foo)   # object里面的__new__方法用来构造对象


obj = Foo('zxc')
print(obj)  # <__main__.Foo object at 0x000002CADD5C0048>

   __new__方法的使用:单例模式

  一种程序设计模式:一个类始终只有一个实例

class Foo:
    __instance = False

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

    def __new__(cls, *args, **kwargs):
        if cls.__instance:    # 当实例化一个对象之后,后面的实例化就使用之前的对象
            return cls.__instance
        cls.__instance = object.__new__(cls)
        return cls.__instance


a = Foo('zxc', 25)
b = Foo('zxf', 22)
print(a.__dict__)  # {'name': 'zxf', 'age': 22}
print(b.__dict__)  # {'name': 'zxf', 'age': 22}
b.hobby = 'read'
print(a.hobby)  # read
# a和b是同一个对象

  __eq__和__hash__

class Foo:
    def __init__(self, name):
        self.name = name


a = Foo('zxc')
b = Foo('zxc')
print(a == b)  # False  正常一个类的两个对象即使属性一样他还是不同的

class Foo:
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        if self.name == other.name:
            return True
        else:
            return False


a = Foo('zxc')
b = Foo('zxc')
print(a)  # <__main__.Foo object at 0x000001543BA60048>
print(b)  # <__main__.Foo object at 0x000001543BA604E0>
print(a == b)  # True  a和b并不相同,但结果却是True,说明==比较时调用的就是__eq__方法,默认使用的都是object的__eq__方法
class Foo:
    def __hash__(self):
        return 10


a = Foo()
print(hash(a))  # 10   内置函数hash调用的就是对象的__hash__方法

   set会依赖__eq__和__hash__

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

    def __hash__(self):
        return hash(self.name+self.sex)

    def __eq__(self, other):
        if self.name == other.name and self.sex == other.sex:
            return True
        else:
            return False


a = Foo('zxc', 25, '')
b = Foo('zxc', 24, '')
print(set([a, b]))  # {<__main__.Foo object at 0x000002BFB7FC04E0>}
# 当name和sex相同时,a和b被认为是同一个,set后去重

# 注释掉类里的__hash__方法
print(set([a, b]))  # 报错 显示类Foo不能哈希  说明set依赖对象的__hash__方法

# 注释掉类里的__eq__方法
print(set([a, b]))  # 结果还是两个元素 并没有去重  说明set的去重还依赖对象的__eq__方法返回结果

  __len__

class Foo:
    def __len__(self):
        return 10


a = Foo()
print(len(a))  # 10   内置函数len调用的就是对象的__len__方法,默认使用的都是object的__len__方法
原文地址:https://www.cnblogs.com/zxc-Weblog/p/8336925.html