2.python类

写在前面

利用class定义(类定义)实现抽象数据类型.
本节从例子出发介绍class定义的使用、其结构和主要设施;下一节将进一步讨论python中基于class的编程技术,成为面向对象技术.

python把内置对象都看作是类.

0.有理数类
class Rationa10:
    def __init__(self, num, den=1):
        # self.fname形式的写法表示本类实例对象的属性 fname是属性名
        self.num = num #分子
        self.den = den #分母

    '''用于有理数相加'''    
    def plus(self, other):
        # other传另一个实例对象进去
        num = self.num * other.den + self.den * other.num
        den = self.den * other.den
        return Rationa10(num, den)
    
    def print(self):
        print(str(self.num) + '/' + str(self.den))

if __name__ == "__main__":
    r1 = Rationa10(3, 5)
    r2 = r1.plus(Rationa10(7, 15))
    r2.print()

#输出结果:80/75
  • 在类里面定义的函数叫做这个类的方法.在这里定义了三个方法,都是操作类实例对象的方法(实例方法),最明显的特征是函数的第一个参数是self
  • __init__()是初始化方法,在创建实例化对象的时候会自动调用
  • r1.plus(Rationa10(7, 15))r1为plus方法的调用对象,方法中的self将约束于该对象,实参表达式Rationa10(7, 15)它将作为plus方法的第二个参数约束到形参another.简单来说,在这里,r1 = self ;Rationa10(7, 15) = another

1.类定义进阶

类定义的重要作用之一就是支持创建抽象的数据类型

我们将表示有理数类进行优化,它可以实现以下功能:

  • 约去其分字分母的最大公约数进行有理数的化简及异常处理
  • 有理数+ 、-、*、//、==、>、<
  • print输出str类型的实例化对象
class Rationa10:
    @staticmethod
    def _gcd(m, n):
        if n == 0:
            m, n = n, m
        while m != 0:
            m, n = n % m, m
        return n

    def __init__(self, num, den=1):
        if not isinstance(num, int) or not isinstance(den, int):
            raise TypeError
        if den == 0:
            raise ZeroDivisionError
        sign = 1
        if num < 0:
            num, sign = -num, -sign
        if den < 0:
            den, sign = -den, -sign
        g = Rationa10._gcd(num, den)
        self._num = sign * (num//g) #分子
        self._den = den // g        #分母
        
    def num(self): return self._num

    def den(self): return self._den

    def __add__(self, another):       #用于有理数相加 +
        num = (self._num * another.den()
              + self._den * another.num())
        den = self._den * another.den()
        return Rationa10(num, den)
    
    def __sub__(self, another):       #用于有理数相加 -
        num = (self._num * another.den()
              + self._den * another.num())
        den = self._den * another.den
        return Rationa10(num, den)
    def __mul__(self, another):       #用于有理数相乘 *
        return Rationa10(self._num * another.num(),
                         self._den * another.den())
    
    def __floordiv__(self, another):  #用于有理数相除 //
        if another.num == 0:
            raise ZeroDivisionError
        return Rationa10(self._num * another.den(),
                         self._den * another.num())

    def __eq__(self, another):        #比较运算符 ==
        return self._num * another.den() == self._den * another.num()
        
    def __lt__(self, another):        #比较运算符 <
        return self._num * another.den() < self._den * another.num()

    def __gt__(self, another):        #比较运算符 >
        return self._num * another.den() > self._den * another.num()
        
    def __str__(self):                #把该类对象转换到字符串
        return str(self._num) + '/' + str(self._den) 

    def print(self):
        print(self._num, '/', self._den)

if __name__ == "__main__":
    #初始化方法的默认参数保证用整数直接创建有理数
    five = Rationa10(5)
    print(five)
    print(type(five))

    x = Rationa10(3, 5)
    #实例化对象x调用该类中的实例方法print()
    x.print()

    #由于有理数类定义了str转换函数,可以直接用标准函数print输出
    print("Two thirds are", Rationa10(2, 3))  
    #使用类中定义的算术运算符和条件运算符
    y = five + x * Rationa10(5, 17)
    print(y)
    if y < Rationa10(123, 11):
        print("small")

结果输出如下:

5/1

3 / 5
Two thirds are 2/3
88/17
small

代码解析:

  • '_'(一个下划线):人们约定,在一个类定义里,由下划线_开头的属性名(和函数名)都当作内部使用的名字,不应该在这个类之外使用.(虽然使用了也不会报错,但约定必定是约定!遵守!)
  • '__'(两个下划线):python对类定义里以两个下划线开头(但不以两个下划线结尾)的名字做了特殊处理,使得在类定义之外不能直接用这个名字访问.一意孤行要访问的话会报错.
  • @staticmethod:静态方法的修饰符。对于静态方法,不应该有self参数,可以通过其所在类的名字出发通过圆点形式调用,也可以从该类的对象出发通过圆点的形式调用.本质上来说,静态方法就是在类里面定义的普通函数,但也是该类的局部函数。
  • 异常处理:有理数的分母不能为0;有理数的分子和分母都应该为整数;初始化的实参可能有正有负,这里采用分子的正负表示有理数的正负;进行两个有理数整除操作的时候,作为分母的那方有理数不能为0;
  • __str__:为了便于输出,在类里定义一个把该类的对象转换到字符串的方法
  • 魔法方法/:__truediv__ ; %:__mod__ ; !=:__ne__ ; <=:__le__ ; >=:__ge__

2.python采用的ADT描述形式

为了更好的用python面向对象的技术和类结构定义各种数据类型,使用的ADT描述将模仿python类定义的形式,也认为ADT描述的是一个类型

2.python类_第1张图片
ADT描述形式python
  • ADT的基本创建函数将以self作为第一个参数,表示被创建的对象,其它参数表示为正确创建对象时候需要提供的其它信息
  • 在ADT描述中的每个操作也都以self作为第一个参数,表示被操作的对象
  • 定义二元运算时也采用同样的形式,其参数表将包括self另一个同类型对象,操作返回的是运算生成的结果对象
  • 写ADT定义时,有时还是采用写参数类型的形式,用于说明操作对具体参数的类型要求,在很多情况下,这样写可以省略一些文字说明

你可能感兴趣的:(2.python类)