python之魔法方法

is 和 == 的关系
'''
== 值相等    值运算
is 内存地址相等 身份运算
is 要求更苛刻
    不仅要求值相等,还要求内存地址相同
'''

a = 111
b = 111
a == b  # 值相等    值运算使用
a is b  # 值相等内存地址不相等使用
is 和 isinstance的关系
class A: pass
class B(A): pass
b = B()
print(isinstance(b, B))
print(isinstance(b, A))
print(issubclass(B, A))

class Mystr(str):pass
ms = Mystr('alex')
print(ms)
print(type(ms) is str)  # 不包含继承关系,只管一层
print(isinstance('alex', str)) # 包含所有的继承关系
__call__方法 相当于 对象()
class A:
    def __call__(self, *args, **kwargs):
        print('执行call方法了')
    def call(self):
        print('执行call方法了')
class B:
    def __init__(self,cls):
        print('在实例化A之前做一些事情')
        self.a = cls()
        self.a()
        print('在实例化A之后做一些事情')
a = A()
a()  # 对象() == 相当于调用__call__方法
a.call()

A()() # 类名()() ,相当于先实例化得到一个对象,再对对象(),==>和上面的结果一样,相当于调用__call__方法
B(A)
iter和next例子
# iter和next的例子
# __iter__ iter(obj)
# __next__ next
def iter(obj):
   return obj.__iter__()  # 返回迭代对象

li = [1,2,3]
print(iter(li))

__len__    len()

class Mylist:
    def __init__(self):
        self.li = [1,2,3]
    def __len__(self):
        print('len')
        # return len(self.li)
        return len(self.__dict__)  # 有多少个属性

l = Mylist()
print(len(l))
# len(obj)相当于调用了这个对象的__len__方法
# __len__方法return的值就是len函数的返回值
# 如果一个obj对象没有__len__方法,那么len函数会报错


# 练习  写一个类 统计str的长度
# self.s = ''  len(obj) = str的长度

class StrLen:
    def __init__(self,s):
        self.s = s

    def __len__(self):
        return len(self.s)

b = StrLen('adsgsdg')
print(len(b))
__new__   # 构造方法 开劈内存空间的类的构造方法
__init__  # 初始化方法
class Single:
    def __new__(cls, *args, **kwargs):  # 在实例化之后,__init__之前先执行new来创建一块空间
        obj = object.__new__(cls)   # Single的new,Single没有,只能调用object的new方法
        print('new', obj)
        return obj

    def __init__(self):
        print('init', self)

# 1、开辟一个空间,属于对象的
# 2、把对象的空间传给self,执行init
# 3、将这个对象的空间返回给调用者

单例类

# 单例类
class single:
    __ISINSTANCE = None
    def __new__(cls, *args, **kwargs):
        if not cls.__ISINSTANCE:
            cls.__ISINSTANCE = object.__new__(cls)
        return cls.__ISINSTANCE


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

# 不论实例多少个对象结果都是同一个内存空间
a = single('alex',32)
b = single('wang', 43)

print(a.name)
print(b.name)

 __str__ 方法

class Student:
    def __str__(self):
        '''
        :return: 返回自定义内容
        '''
        return f"{self.school} {self.class_name} {self.name} {self.age}"

    def __init__(self, school, class_name, name):
        self.school = school
        self.class_name = class_name
        self.name = name
        self.age = 20


name1 = Student('oldboy', 'py', 'alex')
name2 = Student('oldboy', 'py', 'abc')

print(name1)  # 直接调用对象输出自定义内容,需要使用__str__方法
print(str(name1))   # 内置的数据类型,内置的类,相当于执行__str__
print('学生: %s' % name1)
print(f'学生:{name1}')

# print一个对象相当于调用一个对象的__str__方法
# str(obj),相当于执行obj.__str__方法
# '%s'%obj,相当于执行obj.__str__方法

 __repr__

# %s 和 %r 的区别是 %r显示原字符
print("----%s----" % ('abc'))
print("----%r----" % ('abc'))

"""
__str__ : str(obj) 要求必须实现了__str__,要求这个方法的返回值必须是字符串str类型
  # print %s str

__repr__ 对应repr(obj) %r __repr__是__str__的备胎,当__str__存在时执行__str__返回值 ,__str__不存在时,那么print %s str都会执行__repr__,优先使用__repr__方法。
在子类中使用__str__,先找子类的__str__,没有则向上找,只要父类不是object,就执行父类的__str__。
但是如果除了object之外的父类都没有__str__方法,就执行子类的__repr__方法,如果子类也没有,向上继续找父类中的__repr__方法。如果都没有找到,再执行object类中的__str__方法。
""" class A: def __init__(self, name): self.name = name def __str__(self): return f"str {self.name}" def __repr__(self): return f"repr {self.name}" class B(A): # 优先执行子类方法 def __init__(self, name): self.name = name def __repr__(self): return '****' a = B('alex') print(a) print("%s | %r" % (a, a))

 __del__    del()

# __del__方法

class File:

    def __init__(self, fname):
        self.f = open(fname)

    def read(self):
        print(self.f.read())

    def __del__(self):  # 在清除一个对象在内存中的使用的时候, 会触发这个对象所在的类中的析构方法
        print('执行我了')
        self.f.close()

f = File('chinese.txt')
f.read()

item系列    []

# item系列
    # 对象[] 就需要实现item系列
    # getitem  obj['wioe']
    # setitem  obj['uyr'] = jash
    # delitem  del obj['asfjh']

# 使用反射
class A:
    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, key, value):
        setattr(self, key, value)

    def __delitem__(self, key):
        delattr(self, key)


a = A()
a['s32'] = 'fdfd'
print(a['s32'])
del a['s32']
print(a['s32'])

# 使用列表
class B:
    def __init__(self, li):
        self.li = li

    def __getitem__(self, item):
        return self.li[item]

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

    def __delitem__(self, key):
        self.li.pop(key)


b = B(['111', '222', '333', '444', 'ddd'])
print(b[0])
b[2] = 'sss'
print(b.li)
del b[1]
print(b.li)

 

__hash__     hash()

# __hash__方法  hash()
    # 在同一次执行中,相同的值hash值总是一样的
    # set的去重
    # 字典的快速查找

# hash(obj) #obj内部必须实现了__hash__方法

# 练习题
    # 一个类
    # 对象的属性 : 姓名 性别 年龄 部门
    # 员工管理系统
    # 内部转岗 python开发 - go开发
    # 姓名 性别 年龄 新的部门
    # alex None 83 python
    # alex None 85 luffy

    # 1000个员工
    # 如果几个员工对象的姓名和性别相同,这是一个人
    # 请对这1000个员工做去重

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

    def __hash__(self):
        return hash('%s%s' % (self.name, self.sex))

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


employ_lst = []
for i in range(200):
    employ_lst.append(Employee('alex', i, 'male', 'python'))
for i in range(200):
    employ_lst.append(Employee('wusir', i, 'male', 'python'))
for i in range(200):
    employ_lst.append(Employee('taibai', i, 'male', 'python'))

# print(employ_lst)
employ_set = set(employ_lst)
for person in employ_set:
    print(person.__dict__)

# set集合的去重机制 : 先调用hash,再调用eq,eq不是每次都触发,只有hash值相等的时候才会触发

__eq__     ==

# __eq__方法
    #  ==
    #  set的去重

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

    def __eq__(self, other):
        if self.name == other.name and self.age == other.age:
            return True


a = A('alex', 83)
aa = A('alex', 83)
aa2 = A('alex', 83)
aa3 = A('alex', 83)
aa4 = A('alex', 83)
aa5 = A('alex', 83)
aa6 = A('alex', 83)
print(a, aa)
print(aa3 == aa == aa4)  # ==这个语法 是完全和__eq__

 

posted @ 2019-10-04 11:14  pathping  阅读(167)  评论(0编辑  收藏  举报