类的继承、属性总结、方法总结

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

敲黑板:

  1. cn.think()输出的是子类自定义的方法,既不是第一个父类,也不是第二个父类。如果没有自定义,那输出的是第一个父类的方法。
  2. 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'

所以外部访问时:

  1. 通过对象可以访问类的公有、私有属性,对象的公有属性。不能通过对象访问对象的私有属性和局部变量。
  2. 通过类只能访问类的公有属性,不能访问类的私有属性,更不能访问对象的属性。

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
我是静态方法