面向对象编程
将计算机程序视为一系列的命令集合。包含:
- 数据
- 操作数据的函数
Python中,所有的数据类型都可以视为对象。
面向对象特点:封装,继承,多态。
类的函数和普通函数:类的第一个参数永远是实例变量self,并且调用时不用传递该参数。
如果要让内部属性不被外部访问,可以把属性名称前加上两个下划线__。如果实例的变量名以__开头,就变成了一个私有变量。可以内部访问,不能外部访问。
继承与多态
新的类称为子类(Subclass),而被继承的类被称为基类,父类或者超类(Base class,Super class)。
判断一个变量是否是某个类型可以用isinstance(变量,类型)判断。
在继承关系中,如果一个实例的数据类型是某个子类,那么他的数据类型也可以被看做是父类,但是反过来就不可以。
获取对象信息:
1.type():判断对象类型,当一个变量指向函数或类时,也可以用type()判断。type返回对应的class类型。
2.isinstance():判断一个对象是否是某种类型。
3.dir():获得对象的所有属性和方法。它返回一个包含字符串的list。类似于__xxx__的属性和方法在python中都是有特殊用途的。比如__len__返回长度。如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法。以下代码等价:
len('ABC') 'ABC'.__len__()
常用定制对象:
1.__slots__:定义类时,限制该类的实例能添加的属性。(只对当前类起作用,除非在子类中也定义__slots__,这样,子类允许定义的属性就是自生的__slots__加上分类的)
2.@property:后续更新
3.__str__:使用print(对象名)返回字符串描述,给用户看的。
4.__repr__:直接调用对象名返回的字符串描述,给系统看的。
5.__iter__:类想被for ... in 循环,实现类似于list循环功能,该方法返回一个迭代对象。for循环不断调用failed迭代对象的__next__()方法拿到循环下一个值,指导遇到StopIteration时退出。
我们以斐波那契数列为例,写一个Fib类,可以作用于for循环:
class Fib(object): def __init__(self): self.a,self.b=0,1 def __iter__(self): return self def __next__(self): self.a,self.b=self.b,self.a+self.b if self.a>100000: raise StopIteration() return self.a for n in Fib(): print(n)
6.__getitem__:能够使用功能下标取出元素。
class Fib(object): def __getitem__(self,n): a,b=1,1 for x in range(n): a,b=b,a+b return a f=Fib() for i in range(10): print(f[i])
但是若想要实现切片,实现负数取元素,实现隔几个元素取元素,还需要在__getitem__中做出正确的操作。
若想要是实现切片操作,如下:
class Fib(object): def __getitem__(self,n): if isinstance(n,int): a,b=1,1 for x in range(n): a,b=b,a+b return a if isinstance(n,slice): start=n.start stop=n.stop if start is None: start=0 a,b=1,1 L=[] for x in range(stop): if x>=start: L.append(a) a,b=b,a+b return L f=Fib() print(f[0:5])
7.__getattr__:当对象调用不存在的属性时,Python解释器会试图调用__getattr__方法来尝试获得属性。当在__getattr__中没有的属性时,则返回自己约定的AttributeError的错误。
8.__call__:可以用:对象名()调用定义的__call__()方法。
多重继承:
通过多重继承,一个子类就可以同时获得多个父类的所有功能。