python面向对象:
主要包含的名词有:
- 类:由class声明的属性和方法的集合,定义了所有对象共有的属性和方法,对象就是类的实例。
- 类变量:在class中声明的共有变量,在方法外边声明。
- 方法:类中声明的函数。
- 实例化:创建类的实例,是类的具体对象。
- 继承:在py3中声明的对象默认是继承自object,声明的方法
class A: == class A(object):
拥有object内置的所有魔法方法。
>>> class A:
... pass
>>> dir(A)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>>
三大特性--继承、封装、多态
- 封装:对象就是一个封装了事务的相关的属性和方法、调用类内部的操作,不用关心具体代码实现
- 多态:每个类有多个实例/对象,每个对象在调用同一个方法的时候,实现的结果是不相同的
- 继承:子类继承父类的方法,拥有父类的属性的方法。同时可以对父类的方法进行重写,也可以进行添加自己的功能。
继承:
在开始就说明了对象都是继承自object拥有许多内资的魔法函数。
>>> class B:
... def b(self):
... pass
... def c(self):
... pass
>>> class C(B):
... pass
>>> dir(C)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'b', 'c']
在上边可以看到C 继承自B同时拥有了B的方法 b和c。
在继承的过程中,主要考虑对父类的重写
1、简单重写继承
class M:
def m1(self):
return ('this is m1')
def m2(self):
return ('this id m2')
class N(M):
def m1(self):
return ("this is n1")
n = N()
print(n.m1()) # this is n1
2、super简单继承
这里要明白,add11如果为add那么就是重写了A.add
class A:
def add(self, x):
y = x + 1
print(y)
class B(A):
def add11(self, x):
super().add(x)
b = B()
b.add11(2) # 3
b.add(2) # 3
3、多继承顺序
找到之后就继承,不再执行
class A:
def add(self, x):
y = x + 1
print(y)
class C:
def add(self, x):
y = x - 1
print(y)
class B(C, A):
def add11(self, x):
super().add(x)
class D(A, C):
def add11(self, x):
super().add(x)
b = B()
b.add11(2) # 1
d = D()
d.add11(2) # 3
解决问题一:
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print 'Ahahahah'
else:
print 'No thanks!'
class SongBird(Bird):
def __init__(self):
self.sound = 'Squawk'
def sing(self):
print self.song()
sb = SongBird()
sb.sing() # 能正常输出
sb.eat() # 报错,因为 songgird 中没有 hungry 特性
重写:
class SongBird(Bird):
def __init__(self):
super(SongBird,self).__init__()
self.sound = 'Squawk'
def sing(self):
print self.song()
解决问题二:经典的菱形继承案例,BC 继承 A,然后 D 继承 BC,创造一个 D 的对象。
---> B ---
A --| |--> D
---> C ---
使用 super() 可以很好地避免构造函数被调用两次。
class A():
def __init__(self):
print('enter A')
print('leave A')
class B(A):
def __init__(self):
print('enter B')
super().__init__()
print('leave B')
class C(A):
def __init__(self):
print('enter C')
super().__init__()
print('leave C')
class D(B, C):
def __init__(self):
print('enter D')
super().__init__()
print('leave D')
d = D()
property、staticmethod、classmethod
- property:说白了就是把内置的方法修改成像调用属性一样,原来A.a()现在A.a
- staticmethod:这个就是把函数写在类内部,其实和它没关系,调用的方法就是A.a()或者A.a()
- classmethod:传入cls,其实就是类本身,该函数只能访问到类的数据属性,不能获取实例的数据属性
类方法,实例也可以调用,但是并没有什么用,违反了初衷:类方法就是专门供类使用
class D:
def __init__(self, name):
self.name = name
def d(self):
return self.name
@property
def f(self):
return self.name
@staticmethod
def g():
return 1
@classmethod
def h(cls):
return cls
d = D(1)
print(d.d())
print(d.f)
print(d.name)
print(d.g())
print(D.h())
网友评论