手记

【九月打卡】第4天 Python类的特殊方法

课程内容

  • 类的特殊方法
  • __str__和__repr__方法
  • __len__方法
  • 数学运算
  • __slots__方法
  • __call__方法

学习收获

特殊方法

每个类都有特殊方法,并且以双下划线开头,双下划线结尾。

__str__和__repr__方法

当尝试通过str()方法打印对象的时候,程序会自动调用内部方法__str__
当尝试通过repr()方法将对象转化为供解释器读取的形式的时候,程序会自动调用内部方法__repr__

# coding:utf-8
class Animal:
def __str__(self):
	return '正在打印对象'

def __repr__(self):
	return '给程序员看的'

cat = Animal()

print(str(cat))
print(repr(cat))

__len__方法

如果一个类表现得像一个list,想使用len()函数来获取元素个数时,则需要实现__len__()方法。

class Fib:
    def __init__(self,num):
        self.arr = []
        a = 0
        b = 1
        for x in range(num):
            self.arr.append(a)
            a, b = b, a + b
           
        
    def __len__(self):
        return len(self.arr)
        

f = Fib(10)

print(len(f),f.arr)

数学运算

只要我们的自定义类实现了相关的内建函数,我们的类对象,也可以做到加减乘除。比如有理数的加减乘除。

def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)

class Rational(object):
    def __init__(self, p, q):
        self.p = p
        self.q = q
    def __add__(self, r):
        return Rational(self.p * r.q + self.q * r.p, self.q * r.q)
    def __sub__(self, r):
        return Rational(self.p * r.q - self.q * r.p, self.q * r.q)
    def __mul__(self, r):
        return Rational(self.p * r.p, self.q * r.q)
    def __div__(self, r):
        return Rational(self.p * r.q, self.q * r.p)
    def __str__(self):
        g = gcd(self.p, self.q)
        return '{}/{}'.format(int(self.p/g), int(self.q/g))

r1 = Rational(1, 2)
r2 = Rational(1, 5)
print(r1 + r2)
print(r1 - r2)
print(r1 * r2)
print(r1 / r2)

需要注意__add__()函数,它有一个参数,表示的是运算的第二个操作数,比如:r1 + r2,那么在__add__()方法中的参数,r指的就是r2,这个参数是运算符重载的时候传递的。

__slots__方法

由于Python是动态语言,任何实例在运行期都可以动态地添加属性。

如果要限制添加的属性,就可以利用Python的一个特殊的__slots__来实现。

__slots__的目的是限制当前类所能拥有的属性,避免因为外部属性的操作导致类属性越来越难以管理。

class Person(object):
    __slots__ = ('name','gender')
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender
        
class Student(Person):
    __slots__ = ('score')
    
    def __init__(self,name,gender,score):
        super(Student,self).__init__(name,gender)
        self.score = score
        
    def __str__(self):
        return 'my name is {} , {} and score eq {}'.format(self.name,self.gender,self.score)
        

s = Student('Tom','Male',80)

s.score = 99

s.age  = 12

super没那么简单,当使用的版本是2的时候,声明父类的时候,记得添上object关键字。

另外如果父类中没有声明__solts__的话,只在子类中声明,好像还是可以动态的为对象附加属性。

__call__方法

所有的函数都是可调用对象

如果把一个类实例也变成一个可调用对象,可以实现一个特殊的方法__call__()

换句话说,也就是当把类实例当作函数来调用的时候,会自动触发__call__()函数。

# Enter a code
class Fib(object):
    def __init__(self):
        self.res = []

    def __call__(self, num):
        a = 0
        b = 1
        for x in range(num):
            self.res.append(a)
            a, b = b, a + b
        return self.res

f = Fib()
print(f(10))

打卡截图

0人推荐
随时随地看视频
慕课网APP