python进阶 ---构造方法、可视化方法、hash方法

魔术方法

在python中,所有以'__'包围的方法都是魔术方法,比如类的初始化方法__init__方法。这也是类中最基本的魔术方法,
通过此方法可以定义对象的属性和行为。在对类进行实例化时,首先调用的是基类的__new__方法,__new__方法会取出cls参数,
然后将传入的其他参数传给__init__方法。

比如定义一个Person类

class Person(object):
	def __init__(self,name, age=10)
		pass

tom = Person('tommy') 

在对Person类进行实例化时,Person类会以实参的形式传到基类的__new__方法中(cls参数),然后__new__方法会将其他的实参传给Person类的__init__方法进行初始化。

构造函数__new__与__init__

__new__方法

1.__new__方法是一个静态方法
2.当__new__方法返回值是对象实例时,才会继续调用__init__方法
3.当无返回时,类的初始化方法__init__不会被调用
4.__new__方法很少使用,即使类创建了此方法,即使创建了也需要使用return super().__new__()来使用基类的__new__方法来创建实例并返回给__init__方法

__inite__方法

1.__new__方法与__init__方法共同工作
2.__new__方法用于创建实例,__init__方法用于初始化实例
3.__init__方法不能返回任何值,或者说是返回None

可视化方法
方法意义
__str__str()函数,format()函数,print()函数调用,需要返回对象的字符串表达。如果没有定义,就调用__repr__方法返回字符串表达。如果__repr__方法没有定义,就直接返回对象的内存地址
__repr__内建函数repr()对一个对象获取字符串表达,调用__repr__方法返回字符串表达,如果没定义__repr__则返回对象的内存地址
__bytes__bytes()函数调用,返回一个对象的bytes表达,即返回bytes对象
class Person:
    def __init__(self, name, age=15):
        self._name = name
        self._age = age

    def __str__(self):
        return 'str: {},{} years old'.format(self._name, self._age)

    def __repr__(self):
        return 'repr: {},{} years old'.format(self._name, self._age)

    def __bytes__(self):
        return 'bytes: {} {}'.format(self._name, self._age).encode()
        # import json
        # return json.dumps(self.__dict__).encode()


tom = Person('tom')
print('{}'.format(Person('tom')))
# print([Person('tom')])  # []使用__str__,但其内部使用__repr__
# print([str(Person('tom'))])  # []使用__str__,其中的元素使用str()函数也调用__str__
# print(bytes(Person('tom')))
print(str(tom)) #有则调用str,否则调用repr,否则返回对象
print(repr(tom)) #有则调用,否则返回对象
print(bytes(tom)) #需要显式调用

__str__方法

1.定义了__str__方法,且显示使用print(), format(), str()时,就会调用__str__方法
2.不使用以上函数时,若已经定义了__repr__方法,则调用__repr__方法
3.不使用以上函数,并且也没有定义__str__方法和__repr__方法时,则直接返回对象的类名和对象的内存地址

__repr__方法

1.当没有定义__str__方法时,使用__repr__方法
2.当__str__方法和__repr__方法都没定义时,直接返回类名和对象的内存地址

__bytes__方法

1.需要显式调用此方法才能将对象以bytes形式输出

hash方法

class collections.abc.Hashable
可hash指的是:即不可变的数据结构(数字类型(intfloatbool字符串str元组tuple自定义类的对象)。也可以通过id()函数来获取对象修改前后的id号来确定对象是否可hash,如果id号发生改变,说明生成了新的对象,因此这类对象是可hash的(也就是说一旦修改就生成了新对象,标识符从对原对象的引用变成了对新对象的引用,原对象若引用次数为0则可能被销毁)

from collections.abc import Hashable

L1 = [1,2,3]
S1 = {3,4,5}
D1 = {'a':1}

T1 = (1,2)
a = 'xyz'
b = 1

print(1,isinstance(L1, Hashable)) #列表对象不可hash
print(2,isinstance(S1, Hashable)) #集合不可hash
print(3,isinstance(D1, Hashable)) #字典不可hash

print(4,isinstance(T1, Hashable)) #元组可hash
print(5,isinstance(a, Hashable)) #字符串可hash
print(6,isinstance(b, Hashable)) #固定字符,可hash
print(7,isinstance(list, Hashable)) #这个list指的是list类,可hash
print(8,isinstance(set, Hashable)) #指set类,可hash
方法意义
__hash__调用内建函数hash()的返回值,如果定义了__hash__方法,那么这个类的实例就可hash
class A:
    def __init__(self, name, age=18):
        self.name = name

    def __hash__(self):
        return 1

    def __repr__(self):
        return self.name


a = A('tom')
b = A('tom')
print(a is b) #False,两个对象地址不同
print(id(a), id(b))
print(hash(a), hash(b), hash(A('tom')))
print(a, b, A('tom'))
set1 = {a, b}
print(set1)

以上示例中,虽然a,b进行hash结果一样,但是由于a,b是两个不同的对象,因此,在集合中可以同时存在。但是会存在hash冲突的现象,若要去除hash冲突另外还需要提供__eq__方法

__eq__方法

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

a = A('tom')
b = A('tom')

print(hash(a), hash(b))
s = {hash(a), hash(b)}  #去重
print(s)

__eq__方法判断两个对象的内容是否相等,若相等,则去重。

1.只存在__eq__方法时,类的实例对象是不可hash
2.只存在__hash__方法时,可hash,但是不去重,会存在两个内容相同的对象可加入同一个集合的情况
3.既有__eq__方法和__hash__方法则可hash且会去重

bool方法

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


a = A()

print(1,bool(A)) #True
print(2,bool(a)) #True


class B:
    def __bool__(self):
        return False


print(3,bool(B)) #True
print(4,bool(B())) #False
if B():
    print('Real B instance')


class C:
    def __len__(self):
        return 0


print(5,bool(C)) #False
print(6,bool(C())) #True
if C():
    print(7,'Real C instance') #False
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值