你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

Python基础——魔法方法与异常处理

2021/11/20 17:53:08

魔法方法

  • 魔法方法
    • 一.构造和析构
    • 二.算术运算
    • 三.简单定制
    • 四.属性访问
    • 五.描述符
  • 异常处理
    • 1.异常情况
    • 2.处理异常
  • 练习题

魔法方法

一.构造和析构

1.init(self[,…])
只有在需要进行初始化的时候才重写__init__()方法。同时__init__()方法的返回值一定是None.

class Rectangle:
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def getPeri(self):
        return (self.x + self.y)*2
    def getArea(self):
        return self.x*self.y

2.new(cls[,…])

class CapStr(str):
    def __new__(cls,string):
        string = string.upper()
        return str.__new__(cls,string)
a=CapStr("I love FishC.com")
print(a)

3.del(self)

class C:
    def __init__(self):
        print("我是__init__方法,我被调用了")
    def __del__(self):
        print("我是__del__方法,我被调用了")

二.算术运算

1.常见的算术运算

class New_int(int):
    def __add__(self,other):
        return int.__sub__(self,other)
    def __sub__(self,other):
        return int.__add__(self,other)
a=New_int(3)
b=New_int(4)
print(a+b)
-1
print(a-b)
7

2.反运算
反运算相关的魔法方法与算术运算相关的魔法方法保持一一对应的关系,不同之处就是反运算的魔法方法多了一个" r ",例如,add()就对应__radd__().
反运算中如果a对象的__add__()方法没有实现或者不支持相应的操作,那么Python就会自动调用b的__radd__()方法。

class Nint(int):
    def __radd__(self,other):
        return int.__sub__(other,self)
a = Nint(5)
b = Nint(8)
print(a+b)
13
print(1+b)
-7

3.Python支持的一元操作符
neg()表示正号行为;
pos()表示负号行为;
abs()表示定义abs()函数(取绝对值)被调用的行为;
invert()表示定义按位取反的行为。

三.简单定制

基本要求:
定制一个计时器的类;
start和stop方法代表启动计时和结束计时;
假设计时器对象t1,print(t1)和直接调用t1均显示结果;
当计时器未启动或已经停止计时,调用stop方法会给予温馨的提示;
两个计时器对象可以相加:t1+t2;
只能使用提供的有限资源完成。
案例如下:

import time as t

class MyTimer:
    def __init__(self):
        self.unit = ["年","月","日","小时","分钟","秒"]
        self.prompt="未开始计时"
        self.lasted = []
        self.begin = 0
        self.end = 0
        
    def __str__(self):
        return self.prompt
    __repr__ = __str__


    def __add__(self,other):
        prompt="总共运行了"
        result=[]
        for index in range(6):
            result.append(self.lasted[index]+other.lasted[index])
            if result[index]:
                prompt += (str(result[index])+self.unit[index])
        return prompt
    #开始计时
    def start(self):
        self.begin = t.localtime()
        self.prompt="提示:请先调用stop()开始计时"
        print("计时开始...")
        
    #计时结束
    def stop(self):
        if not self.begin:
            print("提示:请先调用start()开始计时")
        else:
            self.end = t.localtime()
            self._calc()
            print("计时结束")
    #内部方法,计算运行时间
    def _calc(self):
        self.lasted = []
        self.prompt = "总共运行了"
        for index in range(6):
            self.lasted.append(self.end[index] - self.begin[index])
            if self.lasted[index]:
                self.prompt += (str(self.lasted[index])+self.unit[index])
                
        self.begin = 0
        self.end = 0

四.属性访问

1.通常可以通过点(.)操作符的形式去访问对象的属性。

class C:
    def __init__(self):
        self.x="X-man"
c=C()
c.x
"X-man"

2.property()函数使得我们可以用属性去访问属性

class C:
    def __init__(self,size=10):
        self.size=size
    def getSize(self):
        return self.size
    def setSize(self,value):
        self.size=value
    def delSize(self):
        del self.size

    x=property(getSize,setSize,delSize)

3.特殊属性__dict__
__dict__的作用是以字典的形式显示出当前对象的所有属性以及相对应的值。

class Rectangle:
    def __init__(self,width=0,height=0):
        self.width=width
        self.height=height
    def __setattr__(self,name,value):
        if name =="square":
            self.width=value
            self.height=value
        else:
            self.__dict__[name]=value
    def getArea(self):
        return self.width*self.height

五.描述符

get(self,instance,owner):用于访问属性,返回属性的值
set(self,instance,value):将在属性分配操作中调用,不返回任何内容
delete(self,instance):控制删除操作,不返回任何内容

class MyProperty:
    def __init__(self,fget=None,fset=None,fdel=None):
        self.fget=fget
        self.fset=fset
        self.fdel=fdel
    def __get__(self,instance,owner):
        return self.fget(instance)
    def __set__(self,instance,value):
        self.fset(instance,value)
    def __delete__(self,instance):
        self.fdel(instance)
class C:
    def __init__(self):
        self._x=None
    def getX(self):
        return self._x
    def setX(self,value):
        self._x=value
    def delX(self):
        del self._x
    x=MyProperty(getX,setX,delX)
    #先执行上述代码
    c=C()
    c.x="X-man"
    c.x
    "X-man"
    c._x
    "X-man"

异常处理

1.异常情况

#AssertionError:断言语句失败
my_list=["小甲鱼"]
assert len(my_list)>0
print(my_list.pop())
assert len(my_list)>0
#AttributeError:尝试访问未知的对象属性
my_list=[]
my_list.fishc
#IndexError:索引超出序列的范围
my_list=[1,2,3]
my_list[3]
#KeyError:字典中查找一个不存在的关键字
my_dict={"one":1,"two":2,"three":3}
print(my_dict["one"])
print(my_dict["four"])
#NameError:尝试访问一个不存在的变量
print(fishc)
#SyntaxError:Python的语法错误
print"I love fishc.com"
#TypeError:不同类型间的无效操作
1+"1"
#ZeroDivisionError:除数为0
5/0

2.处理异常

(1)except后面跟着多个异常,对这些异常进行统一处理

try:
    int("abc")
    sum = 1+"1"
    f=open("我为什么不是一个文件.txt")
    print(f.read())
    f.close()
except (ValueError,TypeError,OSError)as reason:
    print("出错\n错误原因是:"+str(reason))

(2)finally语句块中的内容就是确保无论如何都将被执行的内容

try:
    f=open("我是一个不存在的文档.txt","w")
    print(f.write("我困了"))
    sum = 1+"1"
except(TypeError,OSError):
    print("出错了")
finally:
    f.close

(3)else语句

try:
    int("123")
except ValueError as reason:
    print("出错了"+str(reason))
else:
    print("没有任何异常")

(4)with语句

try:
    with open("data.txt","w")as f:
        for each_line in f:
            print(each_line)
except OSError as reason:
    print("出错"+str(reason))

练习题

1.定义一个类实现银行帐户的概念,包括的变量有“帐号”和“存款余额” ,包括的方法有“存款”、“取款”和“查询余额”。定义类,创建帐户类的对象,并完成相应操作。

class BankNums:
    def __init__(self, ID, money):
        self.ID = ID
        self.money = money

    def addMoney(self, money):
        self.money += money
        print(f"存入金额:{money}元,余额{self.money}")

    def quMoney(self, money):
        self.money -= money
        print(f"取出金额:{money}元,余额{self.money}")

    def lookMoney(self):
        print(f"余额 %s" % self.money)

user = BankNums(ID=1, money=10)
user.addMoney(90)
user.quMoney(70)
user.lookMoney()

2.定义了一个学生的类 Student,包括成员属性“学号”、“班号”、“姓名”、“性别”、“年龄”,成员方法:“获得学号”、“获得班号”、“获得性别”、“获得姓名”、“获得年龄”。写一个构造方法将所有属性初始化,增加一个方法toString()把 Student类对象的所有信息组合成一个字符串。 添加equals方法:仅当学号相等时,认为两个学生相等。

class Student():
    def __init__(self,name,sec,num1,num2,age):
        self.name =name
        self.sec=sec
        self.num1=num1
        self.num2=num2
        self.age=age
    def getA(self):
        return self.name
    def getB(self):
        return self.sex
    def getC(self):
        return self.num1
    def getD(self):
        return self.num2
    def getE(self):
        return self.age
    def toString(self):
        return self.name,self.sec,self.num1,self.num2,self.age
    def equals(self,other):
        return self.num1==other.num1
        
a=Student("小红","女",21,2,18)
b=Student("小芳","女",21,6,18)
print(a.equals(b))
print(a.toString())

3.定义Point、Circle、Cylinder(点、圆、圆柱) 三个类,三个类都拥有 x,y 属性,而 Circle 又增加了属性radius,Cylinder 类又增加了属性 height。都有获得 x,y 坐标,设置 x,y 坐标,求圆的面积、圆柱的体积的方法。

import math
class Point():
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def getXY(self):
        return self.x,self.y
class Circle(Point):
    def __init__(self,x,y,r):
        super().__init__(x,y)
        self.r=r
    def s(self):
        return math.pi*self.r**2
class Cylinder(Circle):
    def __init__(self,x,y,r,h):
        super().__init__(x,y,r)
        self.h=h
    def v(self):
        return math.pi*self.r**2*self.h
if __name__=="__main__":
    a = Cylinder(2,2,1,5)
    print(a.getXY())
    print(a.s())
    print(a.v())