面向对象是一种编程方式,此编程方式的实现基于对 类 和 对象 的使用。
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
特性:
封装
封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
__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.多态
方法:
类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
静态方法:由类调用;无默认参数;
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中 由于没有经典类,所以上述两种写法都表示新式类。