面向对象是一种编程方式,此编程方式的实现基于对  和 对象 的使用。

Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。

在这里,为文章中使用的词汇做一下说明:
函数:指的是第一个参数不是self的函数,不在类中定义的函数;
方法:指是的第一个参数是self的函数,在在类中定义的函数;
实例:类的对象(对类进行实例化即为对象),instance;

 

 

特性:

封装

封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

__init__ 是封装必不可少的,看列子:

class Init():

    def __init__(self,name,age,gender):
        self.Name = name
        self.Age = age
        self.Gender = gender

obj1 = Init('xiao',15,'男')
obj2 = Init('yao',16,'女')

print(obj1.Name)
print(obj2.Name)

 这样实现了数据封装

xiao
yao

 继承

继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。(此处我们只讨论python3的继承)

通过继承创建的新类称为“子类”或“派生类”。

被继承的类称为“基类”、“父类”或“超类”。

继承的过程,就是从一般到特殊的过程。

要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

class C1():
    def c1(self):
        print('C1')
class C2(C1):
    def c2(self):
        print('C2')
class C3():
    def c3(self):
        print('C3')
    def c1(self):
        print('C3')
class C4(C2,C3):
    def c4(self):
        print('C4')
obj = C4()
obj.c1()
obj1 = C3()
obj1.c1()

 输出结果:

C1
C3

 可见,C4继承C2,C3,C2又继承C1,所以obj会有c1方法。

  类的继承可以总结为:

  1.左侧优先

  class C4(C2,C3) 这里C2比C3优先

  2.深度优先

   上面例子C1和C3都有c1方法,但是最后C4继承的是C1的c1

  3.有共同的父类,最后找父类

 

看图红色箭头表示继承关系,黑色箭头表示查找关系

图一:                                                                                                       图二:

        

3.多态

多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
 
Pyhon不支持多态并且也用不到多态,多态的概念是应用于Java和C#这一类强类型语言中
 
 

方法:

 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
 静态方法:由类调用;无默认参数;
 属性方法:Python中的属性其实是普通方法的变种;  
 内置方法: '__dict__', '__doc__', '__init__', '__module__', '__new__', '__repr__', '__str__' 等;
class Foo:
    def __init__(self, name):
        """ 定义内置方法,至少有一个self参数 """
        self.name = name

    def ord_func(self):
        """ 定义普通方法,至少有一个self参数 """
        print('普通方法')

    @classmethod
    def class_func(cls):
        """ 定义类方法,至少有一个cls参数 """
        print('类方法')

    @staticmethod
    def static_func():
        """ 定义静态方法 ,无默认参数"""
        print('静态方法')

    @property
    def property_fuc(self):
        """ 定义属性方法,至少有一个self参数 """
        print('属性方法')


# 调用普通方法
f = Foo('那么')
f.ord_func()
# 调用类方法
Foo.class_func()
f.class_func()
# 调用静态方法
Foo.static_func()
f.static_func()
# 调用属性方法
f.property_fuc

  实例是可以访问类方法和静态方法的,但不建议这样做,容易混淆。 

变量

变量包括:类变量和实例变量,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同。实例变量属于对象,类变量属于.
类变量在内存中只保存一份,实例变量在每个对象中都要保存一份。
class Province:
    # 类变量
    country = '中国'

    def __init__(self, param1):
        # 实例变量
        self.name = param1
# 直接访问普通字段
obj = Province('北京')
print(obj.name)
# 直接访问静态字段
print(Province.country)
print(obj.country)

  我们可看到同方法相似,实例也是可访问类变量的。

 对于每一个类的变量而言都有两种形式:

  • 公有变量,在任何地方都能访问
  • 私有变量,只有在类的内部才能方法
class A:
    name = "公有类变量"
    def func(self):
        print(A.name)
class B(A):
    def show(self):
        print(A.name)
A.name         # 类访问
obj = A()
obj.func()     # 类内部可以访问
obj_son = B()
obj_son.show() # 派生类中可以访问

  

class C:
    __name = "私有类字段"
    def func(self):
        print(C.__name)
class D(C):
    def show(self):
        print(C.__name)
C.__name       # 类访问            ==> 错误
obj = C()
obj.func()     # 类内部可以访问     ==> 正确
obj_son = D()
obj_son.show() # 派生类中可以访问   ==> 错误

  

class C:

    def __init__(self):
        self.foo = "公有实例变量"

    def func(self):
        print(self.foo)  # 类内部访问

class D(C):
    def show(self):
        print(self.foo)  # 派生类中访问

obj = C()
obj.foo  # 通过对象访问
obj.func()  # 类内部访问
obj_son = D()
obj_son.show()  # 派生类中访问

  

class C:

    def __init__(self):
        self.__foo = "私有实例字段"

    def func(self):

        print(self.__foo) # 类内部访问

class D(C):

    def show(self):
        print(self.__foo)  # 派生类中访问

obj = C()
obj.__foo  # 通过对象访问 ==> 错误
obj.func()  # 类内部访问 ==> 正确
obj_son = D()
obj_son.show()  # 派生类中访问 ==> 错误

  

注:

非要访问私有属性的话,可以通过 对象._类__属性名  (  print(obj._C__foo)  

 

新式类&经典类

新式类很早在2.2就出现了,所以经典类(旧式类)完全是兼容的问题,Python3里的类全部都是新式类.

python2.X中

#新式类
class C(object):
    pass
#经典类
class B:
    pass

python3.X中 由于没有经典类,所以上述两种写法都表示新式类。