python——内置方法补充、异常处理

目录

一、new方法

二、__len__方法

三、__eq__方法

四、__hash__方法

 五、__eq__和__hash__应用

官方解释

六、异常处理

1、什么是异常

2、异常的种类

3、异常处理

4、异常处理的意义

 5、捕获异常

5.1 捕获所有异常

5.2 捕获指定异常

5.3 捕获多个异常

5.4 异常中的else

5.5 异常中的finally

5.6 raise主动触发异常

5.7 采用traceback模块查看异常

6、断言assert

7、自定义异常

7.1、自定义异常的两种方式

7.2、如何手动抛出异常:raise

7.3.捕捉用户手动抛出的异常

8、什么时候使用异常


一、new方法

__init__()是初始化方法,__new__()方法是构造方法,创建一个新的对象

实例化对象的时候,调用__init__()初始化之前,先调用了__new__()方法

__new__()必须要有返回值,返回实例化出来的实例

def __new__(cls, *args, **kwargs):

例子

# -*- coding: utf-8 -*-

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

    def __new__(cls, *args, **kwargs):
        obj=super(Foo, cls).__new__(cls) #利用object的__new__方法创建新的空对象
        obj.__init__(*args,**kwargs)
        return obj

f=Foo('nike') 
print(f.name)
print(f.__dict__)

二、__len__方法

如果一个类表现得像一个list,要获取有多少个元素,就得用 __len__() 函数。

通过len(object)调用

class Student():
    def __init__(self,*args):
        self.names = args
​
    def __len__(self):
        return len(self.names)
​
s = Student("nick","jack","pony")
print(len(s)) #用len直接调用__len__方法
from collections import namedtuple

Card = namedtuple("Card",["rank","suit"]) #这里相当于创建了一个名为Card的类,后面的列表里是类的类属性,没有函数属性
                                          #
class FranchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')
    suits = ['红心','方板','梅花','黑桃']

    def __init__(self):
        self._cards = [(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] #这里是一个列表生成式,
        #将第一个for循环里的值赋值给rank,将第二个for循环里的值赋给suit,这个类只要一实例化就自动生成了一副除了没有大小王的牌
        #每张牌都是用元组来表示的
    def __len__(self):
        return len(self._cards) # choice()方法依赖__len__(self)

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

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

deck = FranchDeck()  #这里相当于创建了一副牌
print(deck[0]) #打印第一张牌
print(deck[2:5]) #打印第2-4张牌
from random import choice,shuffle
print(choice(deck))  #随机抽取一张牌
shuffle(deck) #洗牌
print("洗牌后的第一张",deck[0]) #打印第一张牌

三、__eq__方法

__eq__(slef,other) ,判断self对象是否等于other对象,使用==或者is调用此方法。

class Foo:
​
    def __init__(self,name):
        self.name = name
​
    def __eq__(self, other):
        if self.name == other.name:  #判断如果对象的name属性相等就返回True
            return True
        else:
            return False
​
obj1 = Foo("nick")
obj2 = Foo("nicholas")
print(obj1 is obj2)

四、__hash__方法

获取取一个对象的哈希值,一般来说,对于对象的hash值是基于对象的内存地址生成的,但是重写__hash__方法可以自己定制hash取值的对象

class Foo:
​
    def __init__(self,name,age):
        self.name = name
        self.age = age
​
    def __hash__(self):
        return hash(self.name+str(self.age)) #这里基于对象的两个属性返回hash值
​
​
obj1 = Foo("nick",18)  #注意hash的对象不能是整数
obj2 = Foo("nick",18)
print(hash(obj1))
print(hash(obj2))

注意魔法方法__hash__的使用场景有二:

(1)被内置函数hash()调用

(2)hash类型的集合对自身成员的hash操作:set(),  frozenset([iterable]),   dict(**kwarg)

 五、__eq__和__hash__应用

1. 以下代码前半段只用到了__eq__,因为没涉及可hash集合,也就没有涉及到hash

2、如果自定义类重写了__eq__()方法没有重写__hash__()方法,那么这个类无法作为哈希集合的元素使用(这个hashable collections指的是set、frozenset和dict)

比如哈希集合放的全是对象,只定义的__eq__,没定义__hash__,会报错


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    # def __hash__(self):
    #     print(self.name, '使用了__hash__方法')
    #     return hash(self.name)
 
    def __eq__(self, other):
        print(self.name, '使用了__eq__方法')
        return self.__dict__ == other.__dict__
 
 
person1 = Person('zs', 20)
person2 = Person('ls', 20)
person3 = Person('ww', 30)
person4 = Person('zs', 20)
 
print(person1 == person4)
print(person2 == person3)

set1 = {person1, person2, person3, person4}
print(set1)

输出:
zs 使用了__eq__方法
True
ls 使用了__eq__方法
False
Traceback (most recent call last):
  File "D:/self_study/python_study/class_study/python——内置方法.py", line 88, in <module>
    set1 = {person1, person2, person3, person4}
TypeError: unhashable type: 'Person'

这其实是因为重写__eq__()方法后会默认把__hash__赋为None(文档后面有说),像list一样。如下面测试:

class A:
    def __eq__(self, other):
        pass 
a = A()
 
print(a.__hash__)  
hash(a)
输出: 
None 
TypeError: unhashable type: 'A'

3. 如果自定义类重写了__hash__()方法没有重写__eq__()方法

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def __hash__(self):
        print(self.name, '使用了__hash__方法')
        return hash(self.name)
 
    # def __eq__(self, other):
    #     print(self.name, '使用了__eq__方法')
    #     return self.__dict__ == other.__dict__
 
 
person1 = Person('zs', 20)
person2 = Person('ls', 20)
person3 = Person('ww', 30)
person4 = Person('zs', 20)
 
 
set1 = {person1, person2, person3, person4}
print(set1)

不报错,但不符合需求———我们认为person1与person4是同一个人,他们却都被添加到集合,违背了集合的理念:

zs 使用了__hash__方法
ls 使用了__hash__方法
ww 使用了__hash__方法
zs 使用了__hash__方法
{<__main__.Person object at 0x0000000000719CF8>,
 <__main__.Person object at 0x00000000007192E8>, 
 <__main__.Person objec
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值