Python面向对象编程

面向对象与面向过程

面向对象编程从某种程度上来说是从面向过程进化而来的一种编程方法,下面通过例子,对比:

面向过程:

test_list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
test_list2 = [2, 4, 6, 8, 10]
lists = []
for i in test_list1:
    for j in test_list2:
        if i == j:
            if len(test_list1) > len(test_list2):
                lists.append(i)
            elif len(test_list2) > len(test_list1):
                lists.append(j)
print lists

面向对象:

class BingJi:

    def __init__(self, test_list1, test_list2):
        self.test_list1 = test_list1
        self.test_list2 = test_list2

    def puls(self):
        lists = []
        for i in self.test_list1:
            for j in self.test_list2:
                if i == j:
                    if len(self.test_list1) > len(self.test_list2):
                        lists.append(i)
                    elif len(self.test_list2) > len(self.test_list1):
                        lists.append(j)
        return lists

if __name__ == '__main__':
    test = BingJi([1, 2, 3, 4, 5, 6, 7, 8, 9], [2, 4, 6, 8, 10])
    print test.puls()

这是一个对两个列表取并集的功能的面向对象编程和面向过程编程,相信大家对此有些理解了,对于两者,他的操作对象主体是不同的,对于面向过程,他的操作主体是由函数或者过程进行加工和展现,对于面向对象,是在对象的方法(函数)中进行加工与展现的。也就是数据在对象之间进行传递和交互,最后仍然在对象的方法中进行加工与展现,说白了,面向对象呢,就是结构化了,有很多前辈跟我说这样一句话,每个函数只干一件事,就是对象中每个函数(方法)都去完成一项逻辑操作,当代码量很大时,便于维护与修改,想想看,当技术总监给你一个任务,让你去改某项功能时,如果是面向过程的,你就需要修改大量的代码,但如果是面向对象呢,你只需要修改部分函数(方法)的代码就可以了!

什么是对象?

自然界中,万物皆对象,你所看到的都是对象(是不是很开心,妈妈再也不催我相亲啦^-^)
编程中是计算机为解决某个领域问题所使用的事物(自然界中事物的模型化)
比如说人是一个对象,那么,人的眼睛,鼻子,嘴巴就是属性(特征),吃,跑,走就是方法。在python中,类就是对象,以关键字class来定义一个类。

class Test(object):
    pass

类的名字一定要首字母大写,这是代码规范,详情请看PEP8,class后边的括号里是参数,如果有父类,可以写父类,默认参数object,或者直接就不写:

class Test:
    pass

实例化

实例化类就是建立真实事物,就好你有一套人民币模板,那你就可以印钞票了(当然不可以犯法哟$-$),那么每张钞票就是每次实例。
类实例化需要两个步骤:
1.调用__new__()方法创建实例,__new__()方法自动从object继承
2.调用__init__()方法对其初始化,__init__()方法在类中定义
这两个方法的的调用在类实例化的过程中是在背后默默进行的,我们是看不到他是什么时候调用的以及如何调用的,你实例化后自动在后台进行完了。

类的说明(docstring)

当我们定义一个类的时候,肯定是有目的的,因此在定义类的时候一般给添加一个类的说明,一般紧跟类名行(hang)之后,以三引号包围的字符串。

class Test:
    '''
    我是类的说明
    '''
    pass

如何来查看类的说明:
可以通过help(实例名)或者实例名.__doc__来查看类的说明

# test.py
# coding:utf-8
class Test:
    '''
    我是类的说明
    '''
    pass
if __name__ == '__main__':
    test = Test()
    print help(test)
    print test.__doc__

类的属性

实例属性:

类被实例化以后才会具有的属性叫做实例属性,直接使用即定义:self.<属性名>,self用来代表类的实例的:

# test.py
# coding:utf-8
class Test:

    def __init__(self):
        self.a = 1
        self.b = 10

    def method(self):
        print 'a:', self.a
        print 'b:', self.b

if __name__ == '__main__':
    test = Test()
    test.method()

在类的外面用实例名.属性名的方式定义和引用,一般不建议和使用这种方式,这种方式会导致程序混乱:

# test.py
# coding:utf-8
class Test:

    def __init__(self):
        self.a = 1
        self.b = 10

    def method(self):
        print 'a:', self.a
        print 'b:', self.b

if __name__ == '__main__':
    test = Test()
    test.method()
    test.size = '12'
    print test.size

相同类的实例其实例属性是不相关的:

# test.py
# coding:utf-8
class Test:

    def __init__(self):
        self.a = 1
        self.b = 10

    def method(self):
        print 'a:', self.a
        print 'b:', self.b

if __name__ == '__main__':
    test1 = Test()
    test2 = Test()
    test1.a = 1000
    test2.a = 9999
    print '*' * 15 + '修改实例test1' + '*' * 15
    test1.method()
    print '-' * 15 + '修改实例test2' + '-' * 15
    test2.method()

一般不建议在init()方法之外创建和初始化实例属性
也不推荐类外定义和修改,修改可以单独定义方法。(先将注释1打开运行看结果,再将注释2、3打开运行看结果)

# test.py
# coding:utf-8
class Test:

    def __init__(self):
        self.a = 1
        self.b = 10

    def method(self):
        self.c = 6666

if __name__ == '__main__':
    test = Test()
    print test.a
    print test.b
    # print test.c
    # test.method()
    # print test.c

类属性

类定义后就存在,并且不需要实例化就可以被调用,类属性使得相同类的不同示例共同持有相同变量

# test.py
# coding:utf-8
class Test:
    cla = 'ning'

    def __init__(self):
        self.a = 1
        self.b = 10

    def method(self):
        print Test.cla

if __name__ == '__main__':
    test = Test()
    test.method()

当在类外对类属性进行修改时,会同时影响每个实例的类属性:

# test.py
# coding:utf-8
class Test:
    cla = 'ning'

    def __init__(self):
        self.a = 1
        self.b = 10

    def method(self):
        print Test.cla

if __name__ == '__main__':
    test1 = Test()
    test1.method()
    test2 = Test()
    test2.method()
    Test.cla = 123
    test1.method()
    test2.method()

私有属性

从上述来看,大家会想了,那我能在类外修改属性,是不是有点不安全?确实会有吧,那我们怎么解决呢,就是私有属性了,我们使用__开头的变量名加以标志,这样就只有类对象自己能访问了,或者使用_开头的变量名加以标志,不过这种感觉没啥用,就是给程序员自己看的,他加了一个_跟没加没区别,还是能在外边修改类属性。

# test.py
# coding:utf-8
class Test:

    def __init__(self):
        self.__test = 0

    def method(self):
        print self.__test

if __name__ == '__main__':
    test = Test()
    test.method()
    test.__test = 99
    test.method()
    # print test.__test

当我运行被注释的这行代码时,会发现__test被修改了,变成了99,不是说不能修改吗?其实并没有修改私有属性__test,它其实并不是类里的那个类属性,我们说过,私有属性在类的外部是不能被修改的,在python内部,当你定义了__test这个私有属性后,python会自动对这个属性名进行修改,在外部已经看不到了,当我们在类外实例化修改的时候,他会在类内重新定义一个__test属性,所以他能修改了。

特殊属性

类当中用来保存的元数据(元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。)

__doc__前边讲过
__name__类的名称
__dict__用来保存实例属性的所有属性名以及它的值的,类似一个字典。
__module__是用来保存他所在的模块名
__base__用来保存类的父类

面向对象的三大特点

封装、继承、多态

什么是封装呢?为啥封装?

封装你就可以理解为打包程序代码,把什么打包呢?就是对象的方法和属性,就是把人的眼睛、鼻子、嘴巴等特征,以及吃、跑、走等方法进行打包。
那为啥要封装呢?我封装了我的代码,外界就只能使用他,而无法看到他以及改变他。哪个新闻联播主持人也不想被看到下身穿着大裤衩子直播~~

什么是继承,继承的好处是什么?

继承呢,表面意思你可以这样理解,假如某建林持续多年成为某国首富,开心死了,那么,某达的财产就都让他的儿子某思聪继承了(这样说不会被打击报复吧,我只是一个穷屌丝-_-),某建林创造的财富是不是某思聪拥有了?对,代码中,子类就继承了父类的方法和属性,实现了代码的重(chong)用。

class

什么是多态?多态的好处?

多态呢,就是子类可以继承父类的方法和属性,还可以通过自定义去修改父类的属性和方法;同时呢,这里提及一个概念叫鸭子类型(duck typing),这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子,在鸭子类型中,关注的不是类型本身,而是他是如何使用的,而有些语言是需要接口来实现的。

累了 明天写


热评文章