面向对象(OOP)

面向对象的基本概念

面向过程和面向对象是两种不同的变成方式,对比面向过程的特点,可以更好地了解什么是面向对象

 

过程和函数

过程是早期的一个编程概念,类似于函数,只能执行,但是没有返回值,不仅能执行,还可以返回结果

 

面向过程

把某一个需求的所有步骤从头到尾逐步实现,根据开发需求,将某些功能独立的代码封装成一个又一个函数,最后完成的代码,就是顺序的调用不同的函数

特点

  1.注重步骤与过程,不注重职责分工

  2.如果需求复杂,代码会变得很复杂

  3.开发复杂项目,没有固定的套路,开发难度很大

 

面向对象

  相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法

在完成某一个需求前,首先确定职责,根据职责确定不同的对象,在对象内部封装不同的方法

特点

  1.注重对象和职责,不同的对象承担不同的职责

  2.更加适合应对复杂的需求变化,是专门应对负责项目开发,提供的固定套路

 

类和对象的概念

  类和对象的是面向对象编程中的两个核心概念

 

类是对一群具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用

  特征是属性

  行为是方法

对象

对象是由类创建出来的一个具体存在,可以直接使用

由那个类创建出来的对象,就拥有那个类中定义的属性和方法

程序开发中,应该先有类,再有对象

 

类和对象的关系

类是模板,对象是根据类这个模板创建出来,应该先有类,再有对象

类只有一个,而对象可以有很多个,不同的对象之间属性可能会各不相同

类中定义了什么属性和方法,对象中就有什么属性和方法,不可能多,也不可能少

 

类的设计

设计类的三要素

1.类名这类事物的名字,满足大驼峰命名法

2.属性这类事物具有什么样的特征

3.方法这类事物具有什么样的行为

 

属性和方法的确定

对对象的特征描述,通常可以定义成属性

对象具有的行为,通常可以定义成方法

  提示:需求中没有涉及的属性或者方法在设计类时,不需要考虑

 

面向对象基础语法

 

dir内置函数

在Python中对象几乎是无所不在的,之前学习的变量、数据、函数都是对象

使用内置函数dir传入标识符/数据,可以查看对象内的所有属性及方法

提示:__方法名__格式的方法是Python提供的内置方法/属性

 

 

定义类

  面向对象是更大的封装,在一个类中封装多个方法,这个通过这个类创建出来的对象,就可以直接调用这些方法

格式如下:

class 类名:
    def 方法1(self,参数列表):
        pass
    def 方法2(self,参数列表):
        pass

 

方法的定义格式和之前学习过的函数几乎一样,区别在于第一个参数必须是self

 

创建对象

当一个类定义完成之后,要使用这个类创建对象,语法如下:

对象变量 = 类名()

 

在Python中,要给对象设置属性,非常的容易,但是不推荐使用,因为,对象的属性应该封装在类的内部

类外属性赋值的格式:

对象名.属性名 = “值”

 

由哪个对象吊桶的方法,方法内的self就是那个对象的引用

在类封装的方法内部,self就表示当前调用发的对象自己

调用方式时,程序员不需要传递self参数。

在方法内部

  。可以通过self.访问对象的属性

  。可以通过self.调用其他的对象方法

 

在类的外部,通过变量名.访问对象的属性和方法

在类封装的方法中,通过self.访问对象的属性和方法

 

 

初始化方法

。当使用类名()创建对象是,会自动执行一下操作

  1.未对象在内存中分配空间——创建对象

  2.为对象的属性设置初始值——初始化方法(init)

。这个初始化方法就是__init__ 方法,__init__ 是对象的内置方法

  init方法是专门用来定义类具有哪些属性的方法

 

在初始化方法内部定义属性

。在init方法内部使用self.属性名 = 属性的初始值就可以定义属性

。定义属性之后,在使用类创建的对象,都会拥有该属性

 

在开发中,如果希望在创建对象的同时,就设置对象的属性,可以对init方法改造

格式如下:

class 类:
    def __init__(self, name):
        print("初始化方法 %s" % name)
        self.name = name

 

Python中,当一个对象被从内存中销毁前,会自动调用del方法

 

__str__方法

在Python中,使用print输出对象变量,默认情况下,会输出这个变量引用的对象,是由哪个类创建的对象,以及在内存中的地址

如果在开发中希望,使用print输出对象变量时,能够打印自定义的内容,就可以利用__str__这个内置方法

  注意:__str__方法必须返回一个字符串

 

私有属性和私有方法

在实际开发中,对象的某些属性或方法可能只希望对象的内部使用,不希望在外部被访问到

定义方式

。在定义属性或方法时,在属性名或者方法名前,增加两个下划线,定义的就是私有属性或者方法

 

面向对象的三大特征

1.封装根据职责将属性和方法封装到一个抽象的类中

2.继承实现代码的重用,相同的代码不需要重复的编写

3.多态不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

 

继承的概念

子类拥有父类的所有方法和属性

继承的语法

class 类名(父类名):
    pass

子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发

子类中应该根据职责,封装子类特有的属性和方法

 

继承的传递性

C类从B类继承,B类又从A类继承,那么C类就具有B类和A类的所有属性和方法

子类拥有父类以及父类的父类中封装的所有属性和方法

 

方法的重写

子类拥有父类的所有方法和属性

子类继承支付类,可以直接享受父类中已经封装好的方法,不需要再次开发

应用场景

当父类的方法无法实现子类需求时,可以对方法进行重写(override)

重写父类方法的两种情况:

  1.覆盖父类的方法

  2.对父类方法进行扩展

 

覆盖父类的方法

具体的实现方式,就相当于在子类中定义了一个和父类同名的方法并且实现

 

对父类方法进行扩展

。如果在开发中,子类方法实现中包含父类的方法实现,父类原本封装的方法实现是子类方法的一部分

。就可以使用扩展的访视

1.在子类中重写父类的方法

2.在需要的位置使用super().父类方法来嗲用父类方法的执行

3.代码其他的位置针对子类的需求,编写子类特有的代码实现

关于super

。在Python中super是一个特殊的类

。super()就是使用super类创建出来的对象

。最常使用的场景就是重写父类方式,调用在父类中封装的方法实现

 

父类的私有属性和私有方法

子类对象不能再自己的方法内部,直接访问父类的私有属性或私有方法

子类对象可以通过父类的共有方法间接访问到私有属性或私有方法

  私有属性、方法是对象的隐私,不对外公开,外界以及子类都不能直接访问

  私有属性、方法通常用于做一些内部的事情

 

多继承

概念

子类可以拥有多个父类,并且具有所有父类的属性和方法

语法:

class 子类名(父类名1, 父类名2):
    pass

提示:父类之间存在同名的属性或者方法,应该尽量避免使用多继承

 

新式类与旧式类

object是Python未所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看

以object未基类的类是新式类

建议:如果没有父类,统一继承自object

class 类名(object):
    pass

 

 

多态

面对对象三大特征

1.封装:根据职责将属性和方法封装到一个抽象的类中,是定义类的准则

2.继承:实现代码的重用,相同的代码不需要重复的编写,是设计类的技巧

3.多态:不同的子类对象调用相同的父类方法,产生不同的执行结果,可以增加代码的灵活度

  多态是以继承和重写父类方法为前提,是调用方法的技巧,不会影响到类的内部设计

 

类的结构

1.使用面向对象开发,第一步是设计类

2.使用类名()创建对象,创建对象的动作有两步,在内存中未对象分配空间,为对象初始化

3.对象创建后,内存中就有了一个对象的实实在在的存在——实例

因此,通常也会把:

1.创建出来的对象叫做类的实例

2.创建对象的动作叫做实例化

3.对象的属性叫做实例属性

在程序执行时:

1.对象各自拥有自己的实例属性

2.调用对象方法,可以通过self.  访问自己的属性,调用自己的属性

结论

  每个对象都有自己独立的内存空间,保存各自不同的属性

  多个对象的方法,在内存中只有一份,在调用方法是,需要把对象的引用传递到方法内部

 

类是一个特殊的对象

Python中一切皆对象:

  class AAA:定义的类属于类对象

  obj1 = AAA(): 属于实例对象

。在程序运行时,类同样会被加载到内存

。在Python中,类是一个特殊的对象——类对象

。在程序运行时,类对象在内存中只有一份,使用一个类可以创建出很多个对象实例

。除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法:类属性和方法

。通过类名.的方式可以访问类的属性或者调用类的方法

 

类属性和实例属性

类属性就是类对象中定义的属性,通常记录与这个类相关的特征

实例:

class Tool(object):
    
    # 使用赋值语句定义类属性
    count = 0
    
    def __init__(self, name):
        
        self.name = name
        
        Tool.count += 1
        
# 创建工具对象
tool = Tool("斧头")

# 输出工具对象的总数
print(Tool.count)

 

属性的获取机制

。在Python中属性的获取存在一个向上查找机制

因此,要访问类属性有两种方式:

  1.类名.类属性

  2.对象.类属性(不推荐)

 

注意:

 如果使用  对象.类属性 = 值  赋值语句,只会给对象添加一个属性,而不会影响到类属性值

 

类方法和静态方法

类方法

。类方法就是针对类对象定义的方法,在类方法内部可以直接访问类属性或者调用其他的类方法

语法如下

@classmethod
def 类方法名(cls):
    pass

类方法需要用修饰器@classmethod来标识,第一个参数应该是cls

  。由哪一个类调用的方法,方法内的cls就是哪一个类的引用

  。这个参数和实例方法的第一个参数是self类似

通过类名,调用类方法,调用方法时,不需要传递cls参数

在方法内部

  。可以通过cls.访问类的属性

  。也可以通过cls.调用其他的类方法

示例:

class Tool(object):

    # 使用赋值语句定义类属性
    count = 0
  
    @classmethod
    def show_count(cls):
        print("工具的数量:%s" %  cls.count)

    def __init__(self, name):

        self.name = name

        Tool.count += 1

# 创建工具对象
tool = Tool("斧头")
tool2 = Tool("斧头")
tool3 = Tool("斧头")

# 调用类方法
Tool.show_count()

 

 静态方法

。在开发时,如果需要在类中定义一个既不需要访问实例属性、方法,也不需要访问类属性、方法的方法,可以把这个方法封装成一个静态方法

语法如下:

@staticmethod
def 静态方法名():
    pass

。静态方法需要修饰器@staticmethod来标识,告诉解释器这是一个静态方法

。通过类名.调用静态方法

示例:

class Person(object):

    @staticmethod
    def run():
        print("跑跑跑.....")

# 通过类名.调用静态方法


Person.run()

 

单例

单例设计模式

设计模式是前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对某一特定问题的成熟解决方法,使用设计模式是为了可重用代码,让代码更容易被他人理解、保证代码可靠性

单例设计模式

目的——让类创建的对象,在系统中只有唯一的一个实例,每次执行类名()返回的对象,内存地址是相同的

 

__new__方法

。使用类名()创建对象时,Python的解释器首先会调用new方法为对象分配空间

。__new__是一个有object基类提供的内置的静态方法,主要作用有两个:

  在内存中为对象分配空间,返回对象的引用

 

Python的解释器获得对象的引用后,将引用作为第一个参数,传递给init方法

  重写new方法的代码非常固定

。重写new方法一定要 return super.__new__(cls)

。否则Python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法

。注意:new是一个静态方法,在调用时需要主动传递cls参数

new方法重写示例:

class Person(object):

    def __new__(cls, *args, **kwargs):

        # 1.创建对象时,new方法会被自动调用
        print("创建对象,分配空间")

        # 2.为对象分配空间
        instance = super().__new__(cls)

        # 3.返回对象的引用
        return instance

    def __init__(self):
        print("初始化方法")


# 创建对象
p = Person()

print(p)

 

Python中的单例

单例——让类创建的对象,在系统中只有唯一的一个实例

  1.定义一个类属性,初始值是None,用于记录单例对象的引用

  2.重写__new__方法

  3.如果类属性is None,调用父类方法分配空间,并在类属性中记录结果

  4.返回类属性中记录的对象引用

示例:

class Person(object):

    #定义第一个被对象创建对象的引用
    instance = None

    def __new__(cls, *args, **kwargs):

        # 1.判断类属性时候是空
        if cls.instance is None:
            # 2.调用父类的方法,为第一个对象分配空间
            cls.instance = super().__new__(cls)

        # 3.返回类属性保存的对象引用
        return cls.instance


# 创建对象
p1 = Person()
p2 = Person()

print(p1)
print(p2)


# 输出结果
<__main__.Person object at 0x004508F0>
<__main__.Person object at 0x004508F0>

 

只执行一次初始化工作

在每次使用类名创建对象时,Python解释器都会自动调用init方法

想让初始化动作只被执行一次

办法:

1.定义一个类属性,记录是否执行过初始化动作,初始值为False

2.在init方法中,判断类属性,如果False就执行初始化动作

3.然后将类属性设置为True

示例:

class Person(object):

    # 定义类属性
    flag = False

    def __init__(self):

        # 1.判断类属性是否执行过初始化动作
        if Person.flag:
            return
        # 2.如果没有执行
        print("初始化")

        # 3.修改类属性
        Person.flag = True

# 创建对象
p1 = Person()
p2 = Person()


# 输出
初始化

 

posted on 2018-03-27 22:36  今日的小白白  阅读(300)  评论(0)    收藏  举报

导航