1.类的继承
- 继承是面向对象的重要特性之一;
- 继承关系:继承是相对两个类而言的父子关系,子类继承了父类的所有公有属性和方法
- 继承实现了代码重用。
- 继承可以重用已经存在的数据和行为,减少代码的重复编写。Python在类名后使用一对括号来表示继承关系,括号中的类即为父类。
- class Myclass(ParentClass)
如果父类定义了_init_方法,子类必须显式调用父类的_init_方法:
ParentClass._init_(self, [args…])(超过2个参数)
如果子类需要扩展父类的行为,可以添加_init_方法的参数。
1,单一继承:
class Parent(object):
def fun(self):
print “我是父类”
class MyClass(Parent):
def func(self):
print “我是子类”
test = MyClass()
test.fun()
test.func()
class People(object):
color = 'yellow'
def __init__(self): #父类的构造函数
print "init..."
self.dwell = 'earth'
def think(self): #父类的方法
print "i'm a %s" % self.color
class Chinese(People): #定义子类
pass
cn = Chinese()
cn.think() #调用父类的方法
print cn.dwell #调用父类的构造函数的属性
如果父类构造函数_init_()参数有2个+,子类如果要调用父类,必须显式调用
class People(object):
color = 'yellow'
def __init__(self,c):
print "init..."
self.dwell = 'earth'
def think(self):
print "i'm a %s" % self.color
class Chinese(People):
def __init__(self): #显式调用
People.__init__(self,'第二个参数') # 可以改成super函数
cn = Chinese()
cn.think()
print cn.dwell
这里如果没有
def init(self):
People.init(self,'第二个参数')
会报错
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
init...
i'm a yellow
earth
- super函数来继承构造函数.这个操作是为了规避定义父类时用的传统方法导致的报错:
class A() -- 传统方法
class A(object) -- 现在流行的方法
class A(object):
def __init__(self):
print "enter A"
print "leave A"
class B(A):
def __init__(self):
print "enter B"
super(B, self).__init__()
print "leave B"
b = B()
将上面例子的People.init(self,'第二个参数') 换成super函数
class People(object):
color = 'yellow'
def __init__(self,c):
print "init..."
self.dwell = 'earth'
def think(self):
print "i'm a %s" % self.color
class Chinese(People):
def __init__(self):
super(Chinese,self).__init__('第二个参数')
cn = Chinese()
cn.think()
print cn.dwell
另外,子类还可以有自己的方法,比如讲父类的think方法再定义一次:
class People(object):
color = 'yellow'
def __init__(self,c):
print "init..."
self.dwell = 'earth'
def think(self):
print "i'm a %s" % self.color
class Martin(object):
color = 'red'
class Chinese(People,Martin):
def __init__(self):
super(Chinese,self).__init__('第二个参数')
def think(self):
print "子类方法"
cn = Chinese()
cn.think()
此时调用的think方法输出结果是子类自己的
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
init...
子类方法 #不是print "i'm a %s" % self.color
2,多重继承:
- Python支持多重继承,即一个类可以继承多个父类;
- 语法:
class class_name(Parent_c1, Parent_c2,…) - 注意:
当父类中出现多个自定义的_init_方法时,多重继承只执行第一个类的_init_方法,其他不执行。别的方法也是这样的规则,除非子类自定义了相同的方法,否则输出第一个方法
class People(object):
color = 'yellow'
def __init__(self):
print "init..."
self.dwell = 'earth'
def think(self):
print "i'm a %s" % self.color
class Martin(object):
color = 'red'
def __init__(self):
self.dwell = '火星'
class Chinese(People,Martin):
def think(self):
print "子类方法"
cn = Chinese()
cn.think()
print cn.dwell
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
init...
子类方法
earth
敲黑板:
- cn.think()输出的是子类自定义的方法,既不是第一个父类,也不是第二个父类。如果没有自定义,那输出的是第一个父类的方法。
- print cn.dwell输出的是第一个父类People的属性
下面颠倒一下父类顺序,而且注释掉子类自定义的方法:
class People(object):
color = 'yellow'
def __init__(self):
print "init..."
self.dwell = 'earth'
def think(self):
print "i'm a %s" % self.color
class Martin(object):
color = 'red'
def __init__(self):
self.dwell = '火星'
class Chinese(Martin,People):
pass
# def think(self):
# print "子类方法"
cn = Chinese()
cn.think()
print cn.dwell
输出结果:
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
i'm a red
火星
2. 类的属性总结
- 类属性,也是共有属性
- 类的私有属性
- 对象的共有属性
- 对象的私有属性
- 内置属性
- 函数的局部变量
- 全局变量
现在一个个测试输出:
1.外部访问
class Myclass(object):
var1 = '类的公有属性var1'
__var2 = '类的私有属性__var2'
def fun(self):
self.var3 = '对象的公有属性var3'
self.__var4 = '对象的私有属性var4'
var5 = '函数的局部变量'
duixiang = Myclass()
- 通过对象访问 类的公有、私有属性
class Myclass(object):
var1 = '类的公有属性var1'
__var2 = '类的私有属性__var2'
def fun(self):
self.var3 = '对象的公有属性var3'
self.__var4 = '对象的私有属性var4'
var5 = '函数的局部变量'
duixiang = Myclass()
print duixiang.var1
print duixiang._Myclass__var2
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
类的公有属性var1
类的私有属性__var2
- 通过对象访问 对象公有、私有属性
class Myclass(object):
var1 = '类的公有属性var1'
__var2 = '类的私有属性__var2'
def fun(self):
self.var3 = '对象的公有属性var3'
self.__var4 = '对象的私有属性var4'
var5 = '函数的局部变量'
duixiang = Myclass()
duixiang.fun() # 先执行方法,才能调用方法里的属性
print duixiang.var3
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
对象的公有属性var3
- 通过类访问类的公有、私有属性,对象的公有、私有属性
class Myclass(object):
var1 = '类的公有属性var1'
__var2 = '类的私有属性__var2'
def fun(self):
self.var3 = '对象的公有属性var3'
self.__var4 = '对象的私有属性var4'
var5 = '函数的局部变量'
print Myclass.var1
# print Myclass.__var2
print Myclass.var3
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
Traceback (most recent call last):
类的公有属性var1
File "C:/Users/chawn/PycharmProjects/pyex/180108/1.py", line 16, in <module>
print Myclass.var3
AttributeError: type object 'Myclass' has no attribute 'var3'
所以外部访问时:
- 通过对象可以访问类的公有、私有属性,对象的公有属性。不能通过对象访问对象的私有属性和局部变量。
- 通过类只能访问类的公有属性,不能访问类的私有属性,更不能访问对象的属性。
2. 内部访问
- 通过对象访问 类、对象的属性、变量
class Myclass(object):
var1 = '类的公有属性var1'
__var2 = '类的私有属性__var2'
def fun1(self):
self.var3 = '对象的公有属性var3'
self.__var4 = '对象的私有属性var4'
var5 = '函数的局部变量var5'
print self.var1
print self.__var2
print self.var3
print self.__var4
print var5
def fun2(self):
print self.var1
print self.__var2
print self.var3
print self.__var4
# print var5
duixiang = Myclass()
duixiang.fun1() # 调用fun1
print '*' *30 # 30个*分隔
duixiang.fun2() # 调用fun2
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
类的公有属性var1
类的私有属性__var2
对象的公有属性var3
对象的私有属性var4
函数的局部变量var5
******************************
类的公有属性var1
类的私有属性__var2
对象的公有属性var3
对象的私有属性var4
为什么注释def fun2(self):的# print var5?因为var5是fun1的变量,是局部变量。局部变量只能被自己的方法调用,因为不是。
所以内部访问时:
通过对象可以访问类的公有、私有属性,对象的公有属性、私有属性。局部变量不能被另外的方法访问。
3. 类的方法总结
- 公有方法
- 私有方法
- 类方法
- 静态方法
- 内置方法
class Myclass(object):
name = 'test'
def fun1(self):
print self.name
print "我是公有方法"
self.__fun2()
def __fun2(self): # 私有方法只能内部调用
print self.name
print "我是私有方法"
@classmethod # 装饰器
def classfun(self):
print self.name
print "我是类方法"
@staticmethod # 装饰器
def staticfun():
print Myclass.name
print "我是静态方法"
duixiang = Myclass()
duixiang.fun1()
duixiang.classfun()
duixiang.staticfun()
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
test
我是公有方法
test
我是私有方法
test
我是类方法
test
我是静态方法
class Myclass(object):
name = 'test'
def fun1(self):
print self.name
print "我是公有方法"
self.__fun2()
def __fun2(self):
print self.name
print "我是私有方法"
@classmethod
def classfun(self):
print self.name
print "我是类方法"
@staticmethod
def staticfun():
print Myclass.name
print "我是静态方法"
Myclass.classfun()
Myclass.staticfun()
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
test
我是类方法
test
我是静态方法
所以,通过对象可以访问公有方法、私有方法、类方法、静态方法。通过类只能访问类方法、静态方法。
- 通过内置函数访问
class Myclass(object):
name = 'test'
def __init__(self):
self.fun1()
self.__fun2()
self.classfun()
self.staticfun()
def fun1(self):
print self.name
print "我是公有方法"
def __fun2(self):
print self.name
print "我是私有方法"
@classmethod
def classfun(self):
print self.name
print "我是类方法"
@staticmethod
def staticfun():
print Myclass.name
print "我是静态方法"
duixiang = Myclass() #注意这里,只写了对象,没有继续调用函数
C:\Users\chawn\PycharmProjects\pyex\venv\Scripts\python.exe C:/Users/chawn/PycharmProjects/pyex/180108/1.py
test
我是公有方法
test
我是私有方法
test
我是类方法
test
我是静态方法
网友评论