Python——

魔术方法

  • 创建、初始化与销毁
  • hash
  • bool
  • 可视化
  • 运算符重载
  • 容器和大小
  • 可调用对象
  • 上下文管理
  • 反射
  • 描述器
  • 其它杂项

创建、初始化与销毁

__init__方法
__new__方法
__del__方法

class A:
    def __new__(cls, *args, **kwargs):
        print(cls)
        print(args)
        print(kwargs)
        # return None
        return super().__new__(cls)

    def __init__(self, name):
        print('init')
        self.name = name

a = A('tom')
print(a)
print(a.name)

__new__方法
实例化一个对象
该方法返回一个值,如果该值不是cls的实例,则不会调用__init__该方法永远是静态方法
__new__方法很少使用,即使创建了该方法,也会使用return super().new(cls)基类object的方法来创建实例并返回

__init__方法
初始化方法

__del__方法
一般用于结束时归还系统资源,手动调用并不会删除指定实例,只有当引用计数为零时进行清理工作


hash

__hash__
内建函数hash()调用的返回值,返回一个整数(int)。
如果定义这个方法该类实例就可hash。

__eq__
对应==操作符,判断2个对象是否相等,返回bool值

print(hash(1))
print(hash(2))
print(hash('abc'))
print(hash('abc'))
print(hash('abcd'))
print(hash('123'))
print(hash((1,)))
print(hash((1,'a')))

hash(x) x都一样 求得hash应该不变的 幂等性  一般来说 x 不一样 hash应该不同
不同的hash算法 hash冲突 不同的x求得同样的hash值

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

    def __hash__(self):
        return 1

    def __repr__(self):
        return self.name


print(hash(A('tom')))
print((A('tom'), A('tom')))
print([A('tom'), A('tom')])
print('~~~~~~~')
s = {A('tom'), A('tom')}
print(s) # 没有去重
print({tuple('t'), tuple('t')})
print({('tom',),('tom',)})
print({'tom', 'tom'})

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

    def __hash__(self):
        return 1

    def __eq__(self, other):
        return self.name == other.name

    def __repr__(self):
        return self.name

print(hash(A('tom')))
print((A('tom'), A('tom')))
print([A('tom'), A('tom')])
print('~~~~~~~')
s = {A('tom'), A('tom')}
print(s)

__hash__方法只是返回一个hash值座位set的key,但是去重需要__eq__来判断2个对象是否相等,hash值相等,只是hash冲突,不能说明两个对象是相等的。
因此,一般来说提供__hash__方法是为了作为set或者dict的key,所以去重要同时提供__eq__方法。

不可hash对象isinstance(p1, collections.Hashable)一定为False

from collections import Hashable
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __hash__(self):
        return hash((self.x, self.y))

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y


p1 = Point(4, 5)
p2 = Point(4, 5)
print(hash(p1))
print(hash(p2))

print(p1 is p2)
print(p1 == p2)
print(hex(id(p1)), hex(id(p2)))
print(set((p1, p2)))

print(isinstance(p1, Hashable))

bool

__bool__
内建函数bool(),或者对象放在逻辑表达式的位置,调用这个函数返回布尔值。
没有定义__bool__(),就找__len__()返回长度,非0为真。
如果__len__()也没有定义,那么所有实例都返回真。

class A: pass

print(bool(A()))
if A():
    print('real A')

class B:
    def __bool__(self):
        return False

print(bool(B))
print(bool(B()))
if B():
    print('real B')

class C:
    def __len__(self):
        return 0

print(bool(C()))
if C():
    print('real C')

class A:
    def __bool__(self):
        return True

    def __len__(self):
        return 0


if A():
    print('True')

可视化

__repr__
内建函数repr()对一个对象获取字符串表达。
调用__repr__方法返回字符串表达,如果__repr__也没有定义,直接返回object的定义
就是现实内存地址信息

__str__
str()函数、format()函数、print()函数调用,需要返回相对的字符串表达。如果没有定义,就去调用__repr__方法返回字符串表达,如果__repr__没有定义,直接返回对象的内存地址信息

__bytes__
bytes()函数调用,返回一个对象的bytes表达 即返回bytes对象

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

    def __repr__(self):
        return 'repr name={}'.format(self.name)

    def __str__(self):
        return 'str name={}'.format(self.name)

    def __bytes__(self):
        # return self.name.encode()
        import json
        return json.dumps(self.__dict__).encode()

print(A)
print(A('tom'))
print(str(A('tom')))
print('{}'.format(A('jerry')))

print(repr(A('tom')))
print(repr('{}'.format(A('jerry'))))

print('----')
a = A('tom')
print(a)
print([a, a])
print(str({a, a}))
print('{}'.format(a))
print('-----')
print('{}'.format(*{a, a}))
print('{}'.format({a, a}))

print('~~~~')
print(bytes(a))

s = 1
print(s)
s1 = '2'
print(s1)
print([s, s1])

运算符重载

__lt__: <
__le__: <=
__eq__: ==
__gt__: >
__ge__: >=
__ne__: !=
__add__: +           __iadd__: +=
__sub__: -           __isub__: -=
__mul__: *           __imul__: *=
__truediv__: /       __itruediv__: /=
__mod__: %           __imod__: %=
__floordiv__: //     __ifloordiv__: //=
__pow__: **          __ipow__: **=
__divmod__: divmod
class A:
    def __init__(self, name, age=18):
        self.name = name
        self.age = age

    def __sub__(self, other):
        return self.age - other.age

    def __isub__(self, other):
        # return 5
        # self.age -= other.age
        # return self # 返回自身 id不变
        return self.__class__(self.name, self - other) # 重新构建实例 id变化


tom = A('tom')
jerry = A('jerry', 16)
print(tom - jerry)

print(id(tom))
# tom = tom - jerry
# print(tom)

tom -= jerry
print(tom)
print(id(tom))

运算符重载应用场景
往往是用面向对象实现的类,需要做大量的运算,而运算符是这种运算在数学上最常见的表达方式。例如,上例中对运算符进行了重载,实现了新的操作。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值