一. 初始面向对象
- 面向对象思想:将一些数据封装到对象中,在执行方法时,再去对象中获取
- self:本质上是一个参数,就是调用当前方法的那个实例对象
- 对象:基于类实例化出来“一块内存”,默认里面没有数据;经过类的__init__方法,在内存中初始化一些数据
- 三大特性:封装、继承、多态
1. 封装
- 将方法封装到类中或将数据封装到对象中,便于后续使用
- 将数据封装到对象中,在实例化一个对象时,可通过__init__初始化方法在对象中封装一些数据,以便后续使用
2. 继承
- 继承存在意义:将公共的方法提取到父类中,有利于增加代码重用性。
- 将类中公共的方法提取到基类中去实现,子类可以继承父类中的方法和类变量(非拷贝,父类的依然属于父类,子类只是可继承)
- 执行对象方法或访问对象变量时,优先去当前对象所关联的类中找,没有的话才去他的父类中查找
- Python支持多继承:先继承左边、再继承右边;即按照顺序先后进行查找方法或属性,找不到再去后面继承的父类中查找
- self指实例化的对象本身,而非类本身;查找顺序:示例对象本身 -> 对应的类 -> 父类
- python3/python2新式类继承顺序图解(不同于py2的经典类):
继承顺序:A -> B -> D -> G -> H -> K -> C -> E -> F -> M -> N -> P -> object
【从左到右,深度优先,大小钻石,留住顶端。】
3. 多态
- Python默认支持多态
- 在java或其他语言中的多态基于:接口或抽象类和抽象方法来实现,让数据可以以多种形态存在
- Python语言不同于java,对传参数据类型没有任何限制,所以天生支持多态
- java实现多态示例
abstract class Animal{ abstract void eat(); } class Cat extends Animal{ public void eat(){ System.out.println("吃鱼"); } } class Dog extends Animal{ public void eat(){ System.out.println("吃骨头"); } public void work(){ System.out.println("看家"); } } public class Test{ public static void main(String[] args){ obj1 = Cat(); show(obj1); obj2 = Dog(); show(obj2); } public static void show(Animal a){ a.eat(); } }
二. 面向对象成员管理
1. 面向对象包含成员:
- 变量
- 实例变量
- 类变量
- 方法
- 绑定方法
- 类方法
- 静态方法
- 属性
1.1 变量
- 实例变量:属于对象,每个对象中各自维护自己的数据
- 类变量:属于类,可以被所有对象共享,一般用于给对象提供公共数据
- 读写类变量区别:实例对象读取的变量不存在实例对象中时,自动取类中读取类变量;若通过实例对象重写类变量,则类变量不会被改变,而是在实例对象中新建与类变量命名相同的实例变量
1.2 方法
- 绑定方法:默认有个self参数,由对象进行调用(此时self就是调用方法的实例对象本身)(对象、类均可调用)
- 类方法:默认有个cls参数,用类或对象都可以调用(此时cls就是调用方法所属的类) (对象、类均可调用)
- 静态方法:无默认参数,用类和对象都可以调用(对象、类均可调用)
- Python语言较灵活,方法都可以通过对象和类进行调用;而在java、c#等语言中,绑定方法只能由对象调用;类方法或静态方法只能由类调用
- 示例:
class Foo(object): def __init__(self, name, age): self.name = name self.age = age def f1(self): # 通过类调用绑定方法,需传入参数:实例对象 print("绑定方法", self.name) @classmethod def f2(cls): print("类方法", cls) @staticmethod def f3(): print("静态方法")
1.3 属性
- 属性由绑定方法 + 特殊装饰器 组合创造出来的,在调用属性方法时可以不加括号
- 属性实现方法:
- 方式一:基于装饰器
class C(object): @property def x(self): pass @x.setter def x(self, value): pass @x.deleter def x(self): pass obj = C() obj.x # 获取属性 obj.x = 123 # 调用x.setter修饰的方法 del obj.x # 调用x.deleter修饰的方法
- 方式二:基于定义变量
class C(object): def getx(self): pass def setx(self, value): pass def delx(self): pass x = property(getx, setx, delx, " the 'x' property. ") obj = C() obj.x obj.x = 123 del obj.x
- 注:属性和实例变量调用方式相同,故属性名称和实例名称不可重名
- 方式一:基于装饰器
2. 成员修饰符
Python中成员修饰符指:共有、私有
- 共有,在任何地方都可以调用这个成员
- 私有,只有在类的内部才可以调用该成员(两个下划线开头,表示该成员私有)
- 父类中的私有成员,子类无法继承
- 私有成员无法被外部调用,但Python可使用特殊语法访问,如:obj._类名__私有成员名;不推荐不推荐不推荐!
3. 对象嵌套
- 基于面向对象编程时,对象之间可以存在各种各样的关系,如:组合、关联、依赖等(Java中的称呼),即各种嵌套关系;
- 示例一
class Student(object): def __init__(self, name): self.name = name s1 = Student("ali1") s2 = Student("ali2") s3 = Student("ali3") class Classes(object): """班级类""" def __init__(self, title): self.title = title self.student_list = [] def add_student(self, stu_object): self.student_list.append(stu_object) def add_students(self, stu_object_list): for stu in stu_object_list: self.add_student(stu) c1 = Classes("三年二班") c1.add_student(s1) c1.add_students([s1, s2])
- 示例二
class Student(object): """学生类""" def __init__(self, name, class_object): self.name = name self.class_object = class_object class Classes(object): """班级类""" def __init__(self, title): self.title = title c1 = Classes("三年一班") c2 = Classes("三年二班") stu_obj_list = [ Student("ali1", c1), Student("ali2", c2), Student("ali3", c2)]
4. 特殊成员
- __init__,初始化方法
class Foo(object): def __init__(self, name): self.name = name
- __new__,构造方法
class Foo(object): def __init__(self, name): print("第二步:初始化对象,在空对象中创建数据") def __new__(cls, *args, **kwargs): print("第一步:先创建空对象并返回") return object.__new__(cls)
- __call__
class Foo(object): def __call__(self, *args, **kwargs): print("执行call方法") obj = Foo() obj() # 示例对象后+(),调用__call__方法
- __str__
class Foo(object): def __str__(self): return "返回字符串" obj = Foo() data = str(obj) # str(对象):调用__str__方法
- __dict__
class Foo(object): def __init__(self, name, age): self.name = name self.age = age obj = Foo("ali", 17) print(obj.__dict__) # {'name': 'ali', 'age': 17}
- __getitem__、__setitem__、__delitem__ (字典操作类似)
class Foo(object): def __init__(self, name, age): self.name = name self.age = age def __getitem__(self, item): pass def __setitem__(self, key, value): pass def __delitem__(self, key): pass obj = Foo('ali', 17) obj['x1'] # 自动执行__getitem__方法 obj['name2'] = 'ali2' # 自动调用__setitem__方法 del obj['name'] # 自动调用__delitem__方法
- __enter__、__exit__ 上下文管理的语法 (例如语句:with open(‘a.txt’) as f:)
class Foo(object): def __enter__(self): print("进入") def __exit__(self, exc_type, exc_val, exc_tb): print("退出") obj = Foo() with obj as data: print(data)
- __add__,等等… (例如int类型的数据加、减、乘、除操作)
class Foo(object): def __init__(self, name): self.name = name def __add__(self, other): return '{}--{}'.format(self.name, other.name) v1 = Foo("ali1") v2 = Foo("ali2") v3 = v1 + v2 print(v3) # ali1--ali2
- __iter__
三. 面向对象相关内置函数
1. callable, 是否可在后面加括号执行
- 函数
def func(): pass print(callable(func)) # True
- 类
class Foo(object): pass print(callable(Foo)) # True
- 类中具有__call__方法的对象
class Foo(object): pass obj = Foo() print(callable(obj)) # False
class Foo(object): def __call__(self, *args, **kwargs): pass obj = Foo() print(callable(obj)) # True
2. super, 按照继承关系向上找成员
class Top(object):
def message(self, num):
print('Top.message: ', num)
class Base(Top):
pass
class Foo(Base):
def message(self, num):
print('Foo.message: ', num)
super().message(num + 100)
obj = Foo()
obj.message(1)
"""
执行后打印输出内容:
Foo.message: 1
Top.message: 101
"""
若在父类中使用super方法,也要按照实例对象的继承关系继续向上找其他父类,例如:
class Base(object):
def message(self, num):
print('Base.message', num)
super().message(1000)
class Bar(object):
def message(self, num):
print('Bar.message', num)
class Foo(Base, Bar):
pass
obj = Foo()
obj.message(1)
"""
执行代码后打印输出:
Base.message 1
Bar.message 1000
"""
- 应用场景:父类中已实现了某些功能,但我们需要在父类基础上进行功能扩展,重新写一遍?No,此时可以使用super+拓展的代码
3. type,获取一个对象的类型
v1 = 'ali'
print(type(v1)) # <class 'str'>
print(type(v1) == str) # True
v2 = [1, 2, 3]
print(type(v2) == list) # True
class Foo(object):
pass
v3 = Foo()
print(type(v3) == Foo) # True
4. isinstance, 判断对象是否是某个类或其子类的实例
class Top(object):
pass
class Base(Top):
pass
class Foo(Base):
pass
v1 = Foo()
print(isinstance(v1, Foo)) # True
print(isinstance(v1, Base)) # True
print(isinstance(v1, Top)) # True
5. issubclass,判断类是否是某个类的子孙类
class Top(object):
pass
class Base(Top):
pass
class Foo(Base):
pass
print(issubclass(Foo, Base)) # True
print(issubclass(Foo, Top)) # True