课程名称:Python3 进阶教程(新版)
章节名称:第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))