Python学习日记(十四)
继承
- 继承父类的属性和方法,如果子类中定义的属性和方法与父类相同,会覆盖父类,组合纵向关系的类
-
class 子类(父类或基类): .....
class parent: def f(self): print("我是父类") class child(parent): pass c=child() c.f() 我是父类 class parent: def f(self): print("我是父类") class child(parent): def f(self): print("我是子类") c=child() c.f() 我是子类 class parent: def f(self): print("我是父类") class child(parent): def f(self): print("我是子类") c=child() c.f() p=parent() p.f() 我是子类 我是父类
- 在子类中重写初始化函数__init__时要首先把父类的__init__变量加进去,否则会全部覆盖,不能使用父类__init__中的变量
- __ init__特殊方法不应当返回除了None以外的任何对象
-
import random as r class Fish: def __init__(self): self.x=r.randint(0,10) def move(self): self.x-=1 print("我的位置是:",self.x) class Shark(Fish): def __init__(self): self.life='good' S=Shark() S.move() Traceback (most recent call last): File "E:\大三冬\PYTHON\class2.py", line 13, in
S.move() File "E:\大三冬\PYTHON\class2.py", line 6, in move self.x-=1 AttributeError: 'Shark' object has no attribute 'x' - 在子类中使用父类的方法
-
- 调用未绑定的父类方法
可在子类的__init__函数中调用父类的__init__函数,未绑定指的是其中的self任然是指向子类的对象
-
-
import random as r class Fish: def __init__(self): self.x=r.randint(0,10) def move(self): self.x-=1 print("我的位置是:",self.x) class Shark(Fish): def __init__(self): Fish.__init__(self) self.life='good' S=Shark() S.move() 我的位置是: 2
-
-
- 使用super函数
- 可以帮助我们找到父类的方法并自动传入self参数
- 在子类的__init__中使用super.需要的父类的方法即可,不用传self参数
import random as r class Fish: def __init__(self): self.x=r.randint(0,10) def move(self): self.x-=1 print("我的位置是:",self.x) class Shark(Fish): def __init__(self): super().__init__() self.life='good' S=Shark() S.move() 我的位置是: 1
- 多重继承
-
- 继承多个父类,容易导致代码混乱,别轻易使用
-
-
class 子类(父类1,父类2,...): ........
-
组合
- 把类的实例化放到一个新类中,组合多个横向关系的类
-
class Fish: def __init__(self,x): self.num=x class Frog: def __init__(self,x): self.num=x class Pool: def __init__(self,x,y): self.fish=Fish(x) self.frog=Frog(y) def show(self): print('水池中共有%d只鱼和%d只青蛙'%(self.fish.num,self.frog.num)) p=Pool(10,5) p.show() 水池中共有10只鱼和5只青蛙
类、类对象和实例对象
- 实例属性修改后就覆盖了类属性,但是不会改变类属性,相当于将实例属性指向另一个地址,类属性改变也不会影响实例属性
- 类属性是静态的,定义了就一直存在,直到程序退出才消失,即使把类删除类的属性也还在,相当于C语言中的静态变量
-
>>> a=C() >>> b=C() >>> c=C() >>> a.count 0 >>> a.count=10 >>> a.count 10 >>> b.count 0 >>> c.count 0 >>> C.count=5 >>> a.count 10 >>> b.count 0 >>> c.count 0 >>> C.count 5
- 属性的名字和方法冲突时属性会覆盖方法
-
>>> class C: def x(self): print('芜湖') >>> c=C() >>> c.x() 芜湖 >>> c.x=1 >>> c.x 1 >>> c.x() Traceback (most recent call last): File "
", line 1, in c.x() TypeError: 'int' object is not callable
类和对象的BIF
-
issubclass(class, classinfo)
如果第一个参数是第二个参数的一个子类,则返回True,否则返回False:
1??一个类被认为是其自身的子类。
2??classinfo可以是类对象组成的元组,只要class是其中任何一个候选类的子类,则返回True。
3??在其他情况下,会抛出一个TypeError异常>>> class A: pass >>> class B(A): pass >>> issubclass(B,A) True >>> issubclass(B,B) True >>> issubclass(B,object) True >>> class C: pass >>> issubclass(B,C) False >>> issubclass(B,(A,C)) True >>> issubclass(B,111) Traceback (most recent call last): File "
", line 1, in issubclass(B,111) TypeError: issubclass() arg 2 must be a class or tuple of classes
- isinstance(object, classinfo)
- 如果第一个参数是第二个参数的实例对象,则返回True,否则返回False:
1??如果object是classinfo的子类的一个实例,也符号条件。
2??如果第一个参数不是对象,则永远返回False。
3??classinfo可以是类对象组成的元组,只要object是其中任何一个候选对象的实例,则返回True。
4??如果第二个参数不是类或者由类对象组成的元组,会抛出一个TypeError异常。 -
>>> class A: pass >>> class B(A): pass >>> class C: pass >>> issubclass(B,C) False >>> b1 = B() >>> isinstance(b1,B) True >>> isinstance(b1,A) True >>> isinstance(b1,C) False >>> isinstance(b1,object) True >>> isinstance(b1,(A,B,C)) True >>> isinstance(111,A) False >>> isinstance(b1,111) Traceback (most recent call last): File "
", line 1, in isinstance(b1,111) TypeError: isinstance() arg 2 must be a type or tuple of types
-
hasattr(object, name)
attr即attribute的缩写,属性的意思。其作用就是测试一下对象里是否有指定的属性。
第一个参数是对象,第二个参数是属性名(属性的字符串名字),举个例子:
· getattr(object, name[, default]) 返回对象指定的属性值,如果指定的属性不存在,则返回default(可选参数)的值;若没有设置default参数,则抛出AttributeError异常。>>> class C: def __init__(self, x=0): self.x = x >>> c1 = C() >>> hasattr(c1, 'x') True >>> hasattr(c1, 'y') False
>>> class C: def __init__(self, x=0, y=1): self.x = x self.y = y >>> c1 =C() >>> getattr(c1, 'x') 0 >>> getattr(c1, 'y') 1 >>> getattr(c1, 'z') Traceback (most recent call last): File "
", line 1, in getattr(c1, 'z') AttributeError: 'C' object has no attribute 'z' >>> getattr(c1, 'z', '您访问的属性不存在') '您访问的属性不存在'
- setattr(object, name, value)
- 用来设置对象中指定属性的值,如果指定的属性不存在,则新建属性并赋值。
-
>>> setattr(c1, 'x', 111) # 原来有的覆盖 >>> getattr(c1, 'x') 111 >>> setattr(c1, 'z', 2) # 没有新建并赋值 >>> getattr(c1, 'z') 2
- delattr(object, name)
- 用来删除对象中指定的属性,如果属性不存在,则抛出AttributeError异常。
-
>>> delattr(c1, 'x') >>> delattr(c1, 'y') >>> delattr(c1, 'z') >>> delattr(c1, 'aaa') Traceback (most recent call last): File "
", line 1, in delattr(c1, 'aaa') AttributeError: aaa >>>
- property(fget=None, fset=None, fdel=None, doc=None)
- 用来通过属性来设置属性。
-
>>> 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) >>> c = C() >>> c.x 10 >>> c.x = 12 >>> c.x 12 >>> c.size 12 >>> del c.x >>> c.size Traceback (most recent call last): File "
", line 1, in c.size AttributeError: 'C' object has no attribute 'size'
-
property()函数中的三个函数分别对应的是获取属性的方法、设置属性的方法以及删除属性的方法,这样一来,外部的对象就可以通过访问x的方式,来达到获取、设置或删除属性的目的。
当需要更改上例中的getSize、setSize或delSize函数的名称时,如果这些方法是作为接口让用户调用的,那么对用户而言就要修改自己调用的方法名,很麻烦,使用了proprty()后,用户就不需担心这种问题了。
习题:
1、定义一个点(Point)类和直线(Line)类,使用getLen方法可以获得直线的长度。
-
提示: 1??设点A(X1,Y1)、B(X2,Y2),则两点构成的直线长度为|AB| = √(X1-X2)^2 + (Y1-Y2)^2 2??Python中计算开根号可使用math模块中的sqrt函数 3??直线需有两点构成,因此初始化时需要有两个点(Point)对象作为参数 import math class Point(): def __init__(self, x=0, y=0): self.x = x self.y = y def getX(self): return self.x def getY(self): return self.y class Line(): def __init__(self, p1, p2): self.x = p1.getX() - p2.getX() self.y = p1.getY() - p2.getY() self.len = math.sqrt(self.x * self.x + self.y * self.y) def getLen(self): return self.len p1 = Point(1, 1) p2 = Point(1, 4) line = Line(p1, p2) print(line.getLen())