本节对于面向对象的概念不做展开说明。本节主要内容是Python里如何使用面向对象编程。

    分下面几部分:
    1、类的格式
    2、类的实例
    3、类的封装
    4、继承和多态

    下面是一个示例:
    student.py

    通过例子可以发现:
    1、类由开头,类名首字母大写,类名后面的括号表示继承自基类object,所有类都会继承这个类;
    2、类的构造方法是__init__,第一个参数是固定的,永远是self,类里面通过self调用属性和方法,不同于JAVA里使用this

    现在来实例化类:

    1. stu = Student('yjc', 22)
    2. print(stu)
    3. print(stu.name)
    4. stu.print_score()

    输出:

    1. <__main__.Student object at 0x028811F0>
    2. yjc
    3. yjc: 22

    Python里实例化类不用new关键字,而是像使用函数那样即可。调用类里的方法的时候不用传self参数。

    默认的,我们实例化了类后,可以直接访问对象里的属性,也可以去修改对象里的属性:

    1. stu = Student('yjc', 22)
    2. print(stu.name)
    3. stu.print_score()
    4. stu.name = 'Allen'
    5. stu.print_score()

    输出:

    1. yjc
    2. yjc: 22
    3. Allen: 22

    如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问(子类里也不能继承),所以,我们把Student类改一改:

    1. class Student(object):
    2. def __init__(self, name, score):
    3. self.__name = name
    4. self.__score = score
    5. def print_score(self):
    6. print('%s: %s' % (self.__name, self.__score))
    7. stu = Student('yjc', 22)
    8. print(stu.name)

    这时候如果直接访问,就会报错。

    在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类父类超类(Base class、Super class)。

    继承示例:

    1. class Animal(object):
    2. def run(self):
    3. print('runing')
    4. class Dog(Animal):
    5. pass

    以上Dog类继承了Animal类,从而获得父类的方法run()

    1. dog = Dog()

    输出:

    这里子类虽然没有写run()方法,但由于父类已经拥有,所以可以直接继承过来。

    需要注意的是父类的私有变量(__开头的)子类是不能访问,也不能继承的。

    再看看类的多态:

    1. class Dog(Animal):
    2. def run(self):
    3. print('Dog is runing')
    4. class Cat(Animal):
    5. def run(self):
    6. print('Cat is runing')
    7. def runClass(obj):
    8. obj.run()
    9. runClass(Animal())
    10. runClass(Dog())
    11. runClass(Cat())

    输出:

    1. runing
    2. Dog is runing
    3. Cat is runing

    通过例子我们可以看到:
    1、子类如果定义了和父类一样的方法,子类的会覆盖父类;
    2、方法runClass接收一个Animal类,只要含有run()方法,均可正常运行,原因就在于多态。

    但这个绑定的属性属于实例,不属于类,其它Animal的实例是不能访问的。

    在类里直接定义的属性,称为类属性,所有实例均可访问。

    最简单的,我们可以使用type()获取对象的类型:

    1. >>> type(1)
    2. <class 'int'>
    3. >>> type('1')
    4. <class 'str'>
    5. >>> type(True)
    6. <class 'bool'>
    7. >>> type(1.2)
    8. <class 'float'>
    9. >>> type(None)
    10. <class 'NoneType'>
    11. >>> type(abs)
    12. <class 'builtin_function_or_method'>
    13. >>> type(lambda x:x*2)
    14. <class 'function'>
    15. >>> type([1,2])
    16. <class 'list'>
    17. >>> type((1,2))
    18. <class 'tuple'>
    19. >>> type({"name":"yjc"})
    20. <class 'dict'>
    21. >>> type((x for x in range(10)))
    22. <class 'generator'>

    还可以使用types模块进行判断:

    1. >>> import types
    2. >>> def f():pass
    3. ...
    4. >>> type(f)==types.FunctionType
    5. True
    6. >>> type(f)==types.BuiltinFunctionType
    7. False
    8. >>> type(lambda x: x)==types.LambdaType
    9. True
    10. >>> type((x for x in range(10)))==types.GeneratorType
    11. True

    对于类的继承关系,使用isinstance()会更方便:

    1. class Animal(object):
    2. def run(self):
    3. print('runing')
    4. class Dog(Animal):
    5. pass
    6. dog = Dog()
    7. isinstance(dog, Dog)
    8. isinstance(dog,object)

    如果要获得一个对象的所有属性和方法,可以使用dir()函数:

    1. >>> import math
    2. >>> dir(math)
    3. ['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isfinite', 'isinf','isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'pi', 'pow', 'radians', 'sin','sinh', 'sqrt', 'tan', 'tanh', 'trunc']

    类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度。

    getattr()可以获取类的某个属性,setattr()可以设置类的某个属性,getattr()可以判断类是否拥有某个属性:

    1. class Animal(object):
    2. def __init__(self):
    3. self.type = 'animal'
    4. self.area = 'China'
    5. def run(self):
    6. print('runing')
    7. class Dog(Animal):
    8. pass
    9. dog = Dog()
    10. print(hasattr(dog,'type'))
    11. print(hasattr(dog,'run'))
    12. print(hasattr(dog,'name'))
    13. print(getattr(dog,'area'))
    14. # print(getattr(dog,'name'))
    15. setattr(dog, 'name', 'Aia')

    输出:

    使用尝试获取对象的一个不存在属性会报错。可以通过设置默认值避免:

    1. print(getattr(dog,'city', 'beijing')) #beijing