1 概述

  1.1 编程方式

  (1)面向过程:根据业务逻辑从上到下写代码

  (2)函数式:将某功能代码封装在函数中,需要时直接调用

  (3)面向对象:将函数进行分类和封装,让开发更好更快更强

Python使用类(class)和对象(object)进行面向对象编程。

  面向对象三大特性:

  (1)继承:解决代码的复用性问题

  (2)封装:对数据属性严格控制,隔离复杂度

  (3)多态性:增加程序的灵活性与可扩展性

  1.2 类和对象

  类是对象的类型,具有相同属性和行为事物的统称。类是抽象的,使用中会找到这个类的一个具体存在,ex:动物是类,狗是具体的。

  万物皆对象,对象拥有自己的特征和行为。 ex:狗

  类与对象的关系:类是对象的类型,对象是类的实例。类是抽象的概念,而对象是能够摸得着、看得见的实体。二者相辅相成,谁也离不开谁。

2 定义类

  类的组成部分:类型、属性、方法

  Class

    属性列表

    方法列表

class Person(object):
    def __init__(self, name):     # 构造方法,实例化时自动调用
        print('我是构造方法,在实例化的时候调用!')
        self.name = name
    def SayHi(self):      # 方法就是函数
        print('大家好,我是%s!' % self.name)
p = Person("Tom")   # 实例化对象 我是构造方法,在实例化的时候调用!
p.SayHi()   # 大家好,我是Tom!

  2.1 __init__()方法

__init__( )是一个特殊方法属于类的专用方法,称为类的构造函数或初始化方法,方法的前面和后面都有两个下划线。

  每当创建类的实例化对象时,__init__( )方法默认运行,作用是初始化已实例化的对象

  在方法定义中,第一个参数self必不可少,类方法和普通函数的区别就是self,但不是Python关键字,完全可以用其他单词取代,只是按照惯例和标准的规定,推荐使用self。

  2.2 类属性和实例属性

  类属性/类变量:在整个实例化的对象中是公用的,类变量定义在类方法外,通常不作为实例变量使用,函数中的使用格式为:类名.类属性。

  实例属性/变量:定义在类方法中的变量,只作用于当前实例的类,访问方法:实例化对象名.属性

class Person(object):
    country = 'China'
    def __init__(self, name):     # 构造方法,实例化时自动调用
        self.name = name
    def SayHi(self):      # 方法就是函数
        print('大家好,我是%s来自%s!' % (self.name, Person.country))
pr1 = Person("Tom")   # 实例化对象 我是构造方法,在实例化的时候调用!
pr2 = Person('Frank')
pr1.SayHi()     # 大家好,我是Tom来自China!
pr2.SayHi()     # 大家好,我是Frank来自China!

  2.3 内置类属性

__dict__:类的属性(包含一个字典,由“类的属性名.值”组成),实例化类名.__dict__

__doc__:类的文档字符串,实例化类名.__doc__

__name__:类名,实现方式:类名.__name__

__bases__:所有父类构成元素(包含一个所有父类组成的元组)

3 继承和多态

class继承,新的class称为子类(Subclass),被继承的class称为基类、父类或超类。子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法。

class Animal():
    def __init__(self, name, food):
        self.name = name
        self.food = food
    def Eat(self):
        print('%s喜欢吃%s' % (self.name, self.food))
class Dog(Animal):
    def __init__(self, name, food, cry):
        super(Dog, self).__init__(name, food)
        self.cry = cry
    def Cry(self):
        print('%s这样叫:%s' % (self.name, self.cry))
class Cat(Animal):
    def __init__(self, name, food, cry):
        super(Cat, self).__init__(name, food)
        self.cry = cry
    def Cry(self):
        print('%s这样叫:%s' % (self.name, self.cry))
dog = Dog('小狗', '骨头', '汪汪')
dog.Eat()   # 小狗喜欢吃骨头
dog.Cry()   # 小狗这样叫:汪汪
cat = Cat('小猫', '鱼', '喵喵')
cat.Eat()   # 小猫喜欢吃鱼
cat.Cry()   # 小猫这样叫:喵喵

  多继承:一个子类可以继承多个父类是多继承

Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

class Base(object):
    def play(self):
        print('Base is playing!')
class A(Base):  # 继承Base
    def play(self):  # 自动覆盖父类的此方法
        print('A is playing')
class B(Base):  # 继承Base
    def play(self):
        print('B is playing')
class C(A, B):  # 继承A,B
    # pass      # 采用覆盖后的方法:A is playing
    def play(self):     # 调用父类中的方法:Base is playing!
        Base.play(self)
c = C()
c.play()

4 访问限制

  要让内部属性或者方法不被外部访问,可以把在属性或者方法的名称前加上单下划线_, 或者在前面加双下划线__,或者两边加双下划线。

_foo”,只允许类本身和子类可以访问; 

__foo”,外部不可通过“对象.属性名”来访问或者更改,实际将其转化成了“_类名__属性名”;  

__foo__”:系统方法或函数。

class Swan:
    """天鹅类"""
    _neck_swan = "天鹅的脖子很长"  # 保护类型的属性
    def __init__(self):
        print("__init__(): ", Swan._neck_swan)  # 访问保护类型的属性
swan = Swan()  # 实例化Swan类的实例(对象)
print("直接访问:", swan._neck_swan)  # 通过实例名访问保护类型的属性
# __init__():  天鹅的脖子很长
# 直接访问: 天鹅的脖子很长

5 类方法与静态方法

  5.1 实例方法

self”,通过它来传递实例的属性和方法(也可以传类的属性和方法);

  调用:只能由实例对象调用。

  5.2 类方法

  定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);

  调用:实例对象和类对象都可以调用。

应用场景

假设我有一个学生类和一个班级类,想要实现的功能为:
    执行班级人数增加的操作、获得班级的总人数;
    学生类继承自班级类,每实例化一个学生,班级人数都能增加;
    最后,我想定义一些学生,获得班级中的总人数。 

  5.3 静态方法

  定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;

  调用:实例对象和类对象都可以调用。

  静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。

  譬如,我想定义一个关于时间操作的类,其中有一个获取当前时间的函数。

import time
class TimeTest(object):
    def __init__(self, hour, minute, second):
        self.hour = hour
        self.minute = minute
        self.second = second
    @staticmethod
    def showTime():
        return time.strftime("%H:%M:%S", time.localtime())
print(TimeTest.showTime())      # 13:19:34
t = TimeTest(2, 10, 10)
nowTime = t.showTime()
print(nowTime)      # 13:19:34