Reber's Blog

只会一点点编程、只会一点点渗透


Python 的面向对象

0x00 面向对象

  • 面向对象是为了解决系统的可维护性,可扩展性,可重用性

  • 三个基本特征:封装、继承、多态

    • 封装:对一类事物,将其相同特点和功能提取出来,所共有的特点叫做属性,共有的功能就叫做方法,将属性和方法组合在一起就叫做封装。
      如:人具有姓名、年龄、性别,这些就是属性,人可以说话、可以走、可以跑,这些就是方法,封装起来就是一个类,而类的实例化就是对象

    • 继承:继承可以使得子类具有父类的属性和方法,不需要再次编写相同的代码,子类可以对继承的代码进行重写,也可以追加新的属性和方法。
      如:有一个类People,教师就可以继承自People,可以添加自己的属性,如:工资、职工号,也可以添加自己的方法,如:备课、写教案

    • 多态:首先,多态必有继承,没有继承就没有多态,继承后一个父类的引用变量可以指向其任意一个子类对象。
      如:有一个People类,它的子类可以有学生、老师、工人,有多种形态,这就是多态

0x01 类的实例

注意:类中每个方法后面都要写self,self就是当前对象指针

  • 示例一
#!/usr/bin/env python
# -*- coding:utf-8 -*-

# 声明一个People类
class People(object):
    """docstring for People"""
    def __init__(self, name, age):
        super(People, self).__init__()
        self.name = name
        self.age = age

    def running(self):
        print "%s is running" % self.name

    def print_base_msg(self):
        print "Name:%s Age:%d" % (self.name,self.age)

# 继承自People类
class Teacher(People):
    """docstring for Teacher"""
    def __init__(self, name, age, salary):
        super(Teacher, self).__init__(name, age)
        self.name = name
        self.age = age
        self.salary = salary

    def print_base_msg(self): #对父类方法进行重写,会覆盖原方法
        print "Name:%s Age:%d Salary:%d" % (self.name,self.age,self.salary)

# 继承自People类
class Student(People):
    """docstring for Student"""
    def __init__(self, name, age, score):
        super(Student, self).__init__(name, age)
        self.name = name
        self.age = age
        self.score = score

    def print_base_msg(self): #对父类方法进行重写,会覆盖原方法
        print "Name:%s Age:%d Score:%d" % (self.name,self.age,self.score)

t = Teacher('tom',40,13000)
t.running() #tom is running 调用时会先查找当前类中有无此方法,没有的话再从父类查找
t.print_base_msg() #Name:tom Age:40 Salary:13000

s = Student('xiaoming',16,97)
s.running() #xiaoming is running
s.print_base_msg() #Name:xiaoming Age:16 Score:97
  • 示例二
#!/usr/bin/env python
# -*- coding:utf-8 -*-

class A(object):
    """docstring for A"""
    def __init__(self, arg):
        super(A, self).__init__()
        self.arg = arg

    def print_a(self):
        print "A class"

    def print_arg(self):
        print "A output arg: %s" % (self.arg+'-a')

    # 以__开头的是私有成员
    def __print_pravite(self): #子类不能直接用A.__print_pravite()调用它
        a = "A pravite"
        return a

    def get_pravite(self): #可以使用自己的私有方法
        t = self.__print_pravite()
        print t

class B(A):
    """docstring for B"""
    def __init__(self, arg):
        super(B, self).__init__(arg)
        self.arg = arg
 
    def print_b(self):
        print "B class"

    def print_arg(self):
        print "B output arg: %s" % (self.arg+'-b')

    def call_a_fun(self):
        self.print_b()
        self.print_arg()

    def call_b_fun(self):
        A.print_a(self) #调用父类方法。当父类名称改变时子类所有父类名都要变
        super(B, self).print_arg() #调用父类方法,父类名称改变时子类不用调整
        super(B, self).get_pravite() #子类可以使用父类的公有方法
        # super(B, self).__print_pravite() #出错,子类不能使用父类的私有方法

b = B('test')
b.call_b_fun()
b.call_a_fun()

# 输出如下:
# A class
# A output arg: test-a
# A pravite
# B class
# B output arg: test-b
# [Finished in 0.1s]
  • 示例三
#!/usr/bin/env python
# -- coding: utf-8 -*-

class People(object):
    """docstring for People"""

    peoplecount = 0 #类属性

    def __init__(self, name, age, salary):
        super(People, self).__init__()
        self.name = name #对象属性
        self.age = age
        self.__salary = salary #私有属性,外部不能访问
        People.peoplecount += People.peoplecount + 1

    def display_count(self):
        print People.peoplecount #访问类属性

    def display_msg(self):
        print "name:%s age:%d" % (self.name,self.age)

    def set_salary(self, v):
        if v > 0:
            self.__salary = v
        else:
            print "value is error"

    def display_salary(self):
        print "salary:%d" % self.__salary


print People.peoplecount
p1 = People('tom', 21, 20000)
p2 = People('jack', 25, 14900)
p1.display_msg()
p2.display_msg()
p2.display_count()

# 结果如下:
# 0
# name:tom age:21
# name:jack age:25
# 3
# [Finished in 0.1s]