zoukankan      html  css  js  c++  java
  • python进阶-- 03 面向对象编程

    1.定义

    1.1类定义

    在Python中,类通过 class 关键字定义。

    按照 Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的。

    class Person(object): # python 2语法

    # class Person(): # python3语法

        pass

    1.2实例创建

    创建实例使用 类名+(),类似函数调用的形式创建。

    xiaoming = Person()

    xiaohong = Person()

    2属性

    2.1添加实例属性

    由于Python是动态语言,对每一个实例,都可以直接给他们的属性赋值,该属性不必在类中声明。

    class Person(object):

        pass

    p1 = Person()

    p1.name = 'Bart'

    p2 = Person()

    p2.name = 'Adam'

    p3 = Person()

    p3.name = 'Lisa'

    2.2.初始化实例属性

    虽然我们可以自由地给一个实例绑定各种属性,但是,现实世界中,一种类型的实例应该拥有相同名字的属性。

    在定义 Person 类时,可以为Person类添加一个特殊的__init__()方法,当创建实例时,__init__()方法被自动调用,我们就能在此为每个实例都加上统一属性

    举例

    class Person(object):

        def __init__(self, name, gender, birth):

            self.name = name

            self.gender = gender

            self.birth = birth

    2.3.内部属性(私有属性)实现

    如果一个属性由双下划线开头(__),该属性就无法被外部访问

    但是,如果一个属性以"__xxx__"的形式定义,那它又可以被外部访问了,以"__xxx__"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"__xxx__"定义。

    单下划线开头的属性"_xxx"也可以被外部访问。

    重要:即使该私有属性与后来实例绑定的属性同名,并且后来实例的属性被改变,该私有属性也不会改变。

    >>> class test_c(object):

             def __init__(self):

                       self.__test=3

             def get_test_a(self):

                       return self.__test

             test_a=property(get_test_a)

             @property

             def test_b(self):

                       return "bbb"

    >>> a=test_c()

    >>> a.test_a

    3

    >>> a.__test=5

    >>> a.test_a

    3

    2.4类属性

    2.4.1概念

    在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。

    2.4.2特点

    由于Python是动态语言,类属性也是可以动态添加和修改的

    因为类属性只有一份,所以,Person类的address改变时,所有实例访问到的类属性都改变了。

    2.4.3定义

    定义类属性可以直接在 class 中定义:

    #给 Person 类添加一个类属性 count,每创建一个实例,count 属性就加 1,这样就可以统计出一共创建了多少个 Person 的实例。

    class Person(object):

        count=0

        def __init__(self,name):

            Person.count+=1

            self.name=name

    2.4.4类属性与实例属性冲突问题

    当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

    使用实例来修改类属性是错误的,因为你的修改相当于给实例绑定了一个实例属性而已,并没有改变类属性的值。

    class Person(object):

        address = 'Earth'

        def __init__(self, name):

            self.name = name

    p1 = Person('Bob')

    p2 = Person('Alice')

    print 'Person.address = ' + Person.address

    p1.address = 'China'

    print 'p1.address = ' + p1.address

    print 'Person.address = ' + Person.address

    print 'p2.address = ' + p2.address

    2.4.5类属性的__xx

    直接使用“类名.__类属性名”访问无法访问到

    使用“类对象._类名__类属性名”可以访问到

    3.方法

    3.1实例方法

    定义

    实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的。

    def 实例方法名(self,参数1,参数2,...):

        方法块

    调用

    实例.实例方法名(参数1,参数2,...) #self不需要显式传入

    3.2动态将方法添加到实例上

    因为方法也是一个属性,所以,它也可以动态地添加到实例上(只是添加到了此实例上,一般不用)。

    import types

    def fn_get_grade(self):

        if self.score >= 80:

            return 'A'

        if self.score >= 60:

            return 'B'

        return 'C'

    class Person(object):

        def __init__(self, name, score):

            self.name = name

            self.score = score

    p1 = Person('Bob', 90)

    p1.get_grade = types.MethodType(fn_get_grade, p1, Person)

    print p1.get_grade()

    # => A

    p2 = Person('Alice', 65)

    print p2.get_grade()

    # ERROR: AttributeError: 'Person' object has no attribute 'get_grade'

    # 因为p2实例并没有绑定get_grade

    3.3类方法

    3.3.1定义

    通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例;

    类方法的第一个参数将传入类本身,通常将参数名命名为 cls;

    3.3.2特点

    因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。类方法一般用来处理内部类变量。

    3.3.3举例

    下面的 cls.count 实际上相当于 Person.count。

    class Person(object):

        __count = 0

        @classmethod

        def how_many(cls):

            return cls.__count

        def __init__(self,name):

            self.name=name

            Person.__count +=1

    print Person.how_many()

    p1 = Person('Bob')

    print Person.how_many()

    4.继承

    4.1定义

    新类不用重头编写

    新类从现有的类继承,就自动拥有了现有类的所有功能

    新类只需编写现有类缺少的功能

    父类/基类/超类---子类/派生类/继承类

    4.2优点

    复用已有代码

    自动拥有现有类的所有功能

    只需编写缺少的新功能

    4.3特点

    子类 is a 父类 (学生 is a 人)

    Python的任何类必须继承于某个类

    不要忘记调用super(subClass,self).__init__(*args) # args不能再写self

    4.4举例

    class Person(object):

        def __init__(self, name, gender):

            self.name = name

            self.gender = gender

    class Teacher(Person):

        def __init__(self, name, gender, course):

            # 此处也可以写成Person.__init__(self,name,gender)

            super(Teacher,self).__init__(name,gender) # python2.7语法

      # super().__init__(name,gender) # python3语法

            self.course=course

    4.5isinstance()判断类型

    可用来判断某个对象是否为某类型。

    注:一个对象是某子类类型,一定也是该子类的父类对应的类型。

    isinstance(object, class-or-type-or-tuple) -> bool

    # 详见python基础-- 06 函数

    4.6多重继承

    多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用

    举个例子,Python的网络服务器有TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer,而服务器运行模式有 多进程ForkingMixin 和 多线程ThreadingMixin两种。

    要创建多进程模式的 TCPServer:

    class MyTCPServer(TCPServer, ForkingMixin)

        pass

    要创建多线程模式的 UDPServer:

    class MyUDPServer(UDPServer, ThreadingMixin):

        pass

    如果没有多重继承,要实现上述所有可能的组合需要 4x2=8 个子类

    5.多态

    5.1定义

    1.一般地(如JAVA中),父类具有某方法,其子类通过不同实现,实现了该方法,是多态;

    2.由于Python是动态语言,所以,传递给多态方法的参数 x 不一定是父类或基类类型。任何数据类型的实例都可以,只要它有一个与多态方法同样名字的方法即可。

    5.2原理

    1.一般地(如JAVA中),方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止;

    2. 由于Python是动态语言,所以,传递给多态方法的参数 x 不一定是父类或基类类型。任何数据类型的实例都可以,只要它有一个与多态方法同样名字的方法即可。

    5.3动态语言的多态

    动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。

    理解:

    Python提供了open()函数来打开一个磁盘文件,并返回 File 对象。File对象有一个read()方法可以读取文件内容:

    例如,从文件读取内容并解析为JSON结果:

    import json

    f = open('/path/to/file.json', 'r')

    print json.load(f)

    由于Python的动态特性,json.load()并不一定要从一个File对象读取内容。任何对象,只要有read()方法,就称为File-like Object,都可以传给json.load()。

    import json

    class Students(object):

        def __init__(self):

            pass

        def read(self):

            return r'["Tim", "Bob", "Alice"]'

    s = Students()

    print json.load(s)

    # result: [u'Tim', u'Bob', u'Alice']

    6.类中常用函数

    6.1setattr()

             setattr(object, name, value)

             用来设置对象的属性,详细使用help(setattr)查看

  • 相关阅读:
    python学习 day6 (3月7日)
    day05作业---字典
    day04 列表
    python学习 day5 (3月6日)
    python学习 day4 (3月5日)---列表
    Head First JavaScript 第九章:9 异步编码——处理事件
    Head First JavaScript 第八章:8 编写一个应用程序
    Head First JavaScript 第七章:7 类型、相等、转换等系统地讨论类型
    《深入理解C指针》第五章 指针和字符串
    Architecture of a Database System论文——第四章:关系查询处理器
  • 原文地址:https://www.cnblogs.com/yc913344706/p/7749416.html
Copyright © 2011-2022 走看看