浅析python中的面向对象

一、面向过程与面向对象对比

  • 面向过程的程序设计的核心是过程(流水线式思维),过程即是解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
    1>优点:极大的降低了程序的复杂度
    2>缺点:一套流水线或者流程就是用来解决一个问题,比如生产电脑的流水线无法生产汽车,即便要能生产,也得大改生产电脑的流水线,然而,即使是改一个很小的参数或者组件,都会导致整个流水线的改变。
    3>应用场景:一旦完成基本很少改变的场景,即设计过程完成后一般不需要去改变。著名的例子有Linux內核,Apache HTTP Server,以及底层模块等。
  • 面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。对象是特征和技能的结合,其中特征和技能分别对应对象的数据属性和方法属性。
    1>优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中。
    2>缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。
    3>应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都使用面向对象的程序设计。

二、类和对象

  • 1>把一类事物的静态属性和动态可以执行的操作组合在一起所得到的这个概念就是类
  • 2>类的一个个体就是对象,类是抽象的,对象是具体的,实实在在的事物,好比类是制造汽车的图纸,而对象就是由这张图纸制造出来的汽车。
  • 3>对象是特征与技能的结合体,其中特征和技能分别对应对象的数据属性和方法属性
  • 4>对象(实例)本身只有数据属性,但是python的class机制会将类的函数绑定到对象上,称为对象的方法,或者叫绑定方法,绑定方法唯一绑定一个对象,同一个类的方法绑定到不同的对象上,属于不同的方法,内存地址都不会一样
  • 5>创建一个类就会创建一个类的名称空间,用来存储类中定义的所有属性名和方法名。
  • 6>创建一个对象(实例)就会创建一个对象(实例)的名称空间,存放对象(实例)的名字,称为对象(实例)的属性

类的相关方法:

class cat:
    """这是一个猫类"""
    def eat(self):
        print '小猫爱吃鱼'

    def drink(self):
        print '小猫爱喝水'

print cat.__name__      # 类的名字(字符串)
print cat.__doc__       # 类的文档字符串
print cat.__dict__      # 类的字典属性,名称空间
print cat.__module__    # 类定义所在的模块
"""结果如下"""
# cat
# 这是一个猫类
# {'__module__': '__main__', 'drink': <function drink at 0x7f2dbade8a28>, '__doc__': '\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe7\x8c\xab\xe7\xb1\xbb', 'eat': <function eat at 0x7f2dbade89b0>}
# __main__

三、面向对象的基本语法
定义一个只包含方法的类

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

类名:大驼峰命名法
方法的定义格式和之前的函数几乎一样,区别在于第一个参数必须是self。
示例:

# _*_ coding:utf-8 _*_
class Cat:
    def eat(self):
        print '小猫爱吃鱼'

    def drink(self):
        print '小猫要喝水'

"""
创建对象
当一个类定义完成后,要使用这个类来创建对象
对象变量 = 类名()
"""
# 创建猫对象
tom = Cat()
tom.drink()
tom.eat()
"""结果如下"""
# 小猫要喝水
# 小猫爱吃鱼

四、初始化构造函数__init__
初始化构造函数就是在构造对象的同时被对象自动调用,完成对事物的初始化,一个类只要实例化,它一定会调用初始化构造函数。
特点:

  • 1> 一个类中只能有一个初始化构造函数
  • 2> 初始化构造函数没有返回值
  • 3> 可以用它来为每个实例构造自己的特征属性

示例:创建一个学生类,初始化姓名和年龄

# _*_ coding:utf-8 _*_
class Student:
    def __init__(self, name, age):
        # self.属性名 = 属性的初始值
        self.name = name
        self.age = age
        print"name:%s   age:%d" % (self.name, self.age)

# 在构造对象的时候会自动调用初始化构造函数
student1 = Student("Alex", 20)
student2 = Student("Tom", 21)
"""结果如下"""
# name:Alex   age:20
# name:Tom   age:21

五、self关键字的作用
在调用方法的时候,程序员不需要传递self参数(但是定义的时候,第一个参数必须是self)
在方法内部:可以通过< self.属性 >访问对象的属性。
哪一个对象调用的方法,self就是哪一个对象的引用
示例:

# _*_ coding:utf-8 _*_
class Cat:
    def __init__(self):
        print '当前对象的地址:%s' % self

    def eat(self):
        print '%s爱吃鱼' % self.name

    def drink(self):
        print '%s爱喝水' % self.name

tom = Cat()
"""
在日常开发中,不推荐在类的外部给对象增加属性
如果在运行的时候,没有找到属性,程序就会报错
对象包含的属性应该封装在类的内部
"""
tom.name = 'Tom'
tom.eat()
tom.drink()
print tom

lazy_cat = Cat()
# 给对象lazy_cat添加一个属性
lazy_cat.name = 'lazy_cat'
lazy_cat.eat()
lazy_cat.drink()
print lazy_cat
"""结果如下"""
# 当前对象的地址:<__main__.Cat instance at 0x7f2a901ee5f0>
# Tom爱吃鱼
# Tom爱喝水
# <__main__.Cat instance at 0x7f2a901ee5f0>
# 当前对象的地址:<__main__.Cat instance at 0x7f2a901ee638>
# lazy_cat爱吃鱼
# lazy_cat爱喝水
# <__main__.Cat instance at 0x7f2a901ee638>

由以上结果可以看到,tom、lazy_cat、self实际上都是指针变量,存放的是地址,指定的是当前时刻正在调用的那个对象。

六、类的内置方法

  • __del__方法:对象被从内存中销毁前,会被自动调用
  • __str__方法:如果在开发中,希望使用print输出对象变量,该方法能够自定义打印的内容。

示例1:__del__方法

# _*_ coding:utf-8 _*_
class Cat:
    def __init__(self, name):
        self.name = name
        print '%s 来了' % self.name

    def __del__(self):
        print '%s 走了' % self.name

tom = Cat('Tom')
print tom.name
print '*' * 50
"""结果如下"""
# Tom 来了
# Tom
# **************************************************
# Tom 走了

注意这里输出的一行“*“和Tom走了的顺序,对象tom是一个全局变量,只有在全部代码执行完成后,才会被系统回收,所以是先输出了一行“*“,然后才调用了内置方法__del__输出了 Tom 走了。
也可使用del关键字来删除一个对象:
< del 关键字 > 可以删除一个对象,del关键字自己调用__del__方法

示例2:__str__方法

# _*_ coding:utf-8 _*_
class Cat:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        # 必须返回一个字符串
        return '我是 %s' % self.name

tom = Cat('Tom')
print tom
"""结果如下"""
# 我是 Tom

默认在类中若不写__str__方法,再去< print 对象名 >输出的是这个对象的内存地址,对于开发人员知道这个输出的意思,而对于客户来说这个输出是没有意义的,所以我们可以使用__str__来自定义它的输出。
对__del__方法和__str__方法的总结:

  • __del__方法:对象被从内存中销毁前,会被自动调用
  • __str__方法:返回对象的描述信息,print函数输出使用

__del__方法:

  • 当使用类名()创建对象时,为对象分配完空间后,自动调用init方法
  • 当一个对象被从内存中销毁前(把这个对象从内存中删除掉),会自动调用__del__方法

应用场景

  • __init__改造初始化方法,可以让创建对象更加灵活
  • __del__如果希望在对象被销毁前,再做一些事情,可以考虑一下__del__方法

生命周期(出生到死亡)

  • 一个对象从调用类名()创建,生命周期开始
  • 一个对象的__del__方法一但被调用,生命周期结束
  • 在对象的生命周期内,可以访问对象属性,或者让对象调用方法

__str__方法:

  • 使用python输出对象变量,默认情况下,会输出这个变量引用的对象是由哪一个类创建的对象,以及在内存中的地址(十六进制表示)
  • 在开发中,希望使用print输出对象变量时,能够打印自定义的内容,就可以利用__str__这个内置方法

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

  • 私有属性 就是 对象 不希望公开的 属性
  • 私有方法 就是 对象 不希望公开的 方法

定义方法:在属性名或者方法名前加两个下划线(__)
示例:

class Women:
    def __init__(self, name, age):
        self.name = name
        # 定义私有属性
        self.__age = age

    def WomenAge(self):
        print '公有方法访问 ' + '%s 的年龄是 %d' % (self.name, self.__age)

    def __secret(self):
        print '%s 的年龄是 %d' % (self.name, self.__age)

lily = Women('LILY', 18)
# 私有属性,在外界不能被直接访问
# print lily.age
print lily.WomenAge()
# 私有方法,同样不允许外界直接访问
# lily.secret()
"""结果如下"""
# 公有方法访问 LILY 的年龄是 18
# None

一个类中定义的私有属性和私有方法在类的外部不允许直接访问,若在外部访问程序会报错,但是在类内可以访问其定义的私有属性和方法,故我们可以在类内定义一个公有方法WomenAge,让其再调用类内的私有属性,外部对象调用这个公有方法WomenAge,从而实现再外部对类内部的私有属性的访问。

猜你喜欢

转载自blog.csdn.net/oikinkl/article/details/82461956