第4章 面向对象
参考: 面向对象编程, 封装, 继承与派生, 多态与鸭子类型, 绑定方法与非绑定方法, 反射, 内置方法, 元类
一. 列举你所知道的面相对象中的__开头__
结尾的方法及作用,越多越好.
"""
__call__: 调用对象触发其类 或者 父类
__new__: 调用类时触发. 在__init__之前
__init__: 调用类时触发.
__str__: 打印对象时触发
__del__: 对象被回收前触发
__getattr__: 使用点调用属性时属性不存在时触发
__setattr__: 添加/修改属性时触发
__delattr__: 删除属性的时触发
__getattribute__: 使用点调用属性时属性存在或者不存在都触发
__next__: 对迭代器对象进行取值
__iter__: 将可迭代对象转化为迭代器对象(迭代器对象也是可迭代对象)
__enter__: with操作时自动触发, 返回值赋值给as后面的句柄对象
__exit__: with子代码块执行完毕以后自动触发.
三个参数: exc_type, exc_val, exc_db
第一个参数: 异常类型
第二个参数: 异常值
第三个参数: 异常追随信息
如果返回True则在with语句执行的过程中抛出异常不会影响with之后的语句的正常执行
__getitem__: `对象['属性']` 时自动触发
__setitem__: `对象['属性']=值` 时自动触发
__delitem__: `del ['属性']` 时自动触发
__class__: 获取当前类
__module__: 获取当前模块
__eq__: ==比较时自动触发. 等于号右边对象当作参数传入.
__lt__, __gt__
__doc__: 获取文档描述. (提示: 子类继承, 无法获取)
"""
二. 你所知道的能够实现单例模式的方式有哪些,尝试着手写几个?
"""
定义类方法, 利用类实例化对象自动触发__new__方法, 自定义元类, 函数装饰器, 类装饰器, 导入模块
"""
1. 定义类方法
# settings.py文件内容如下:
"""
host = '127.0.0.1'
port = 8080
"""
import settings
class MySQL:
_instance = None
def __init__(self, host, port):
self.host = host
self.port = port
@classmethod
def singleton(cls):
if not MySQL._instance:
MySQL._instance = MySQL(settings.host, settings.port)
return MySQL._instance
obj1 = MySQL('127.0.0.1', 8080)
obj2 = MySQL('127.0.0.1', 8080)
print(obj1 is obj2) # False
obj1 = MySQL.singleton()
obj2 = MySQL.singleton()
print(obj1 is obj2) # True
2. 利用类实例化对象自动触发__new__
方法
class MySQL:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = object.__new__(cls)
return cls._instance
obj1 = MySQL()
obj2 = MySQL()
print(obj1 is obj2) # True
3. 自定义元类
# settings.py文件内容如下:
"""
host = '127.0.0.1'
port = 8080
"""
import settings
class MyMeta(type):
def __init__(self, class_name, class_bases, class_dict):
# self._instance = object.__new__(self)
# self.__init__(self._instance, settings.host, settings.port)
self._instance = super().__call__(settings.host, settings.port)
super().__init__(class_name, class_bases, class_dict)
def __call__(self, *args, **kwargs):
if args or kwargs:
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs)
return obj
return self._instance
class MySQL(metaclass=MyMeta):
def __init__(self, ip, port):
self.ip = ip
self.port = port
obj1 = MySQL('127.0.0.1', 8080)
obj2 = MySQL('127.0.0.1', 8080)
print(obj1 is obj2) # False
obj1 = MySQL()
obj2 = MySQL()
print(obj1 is obj2) # True
4. 函数装饰器
# settings.py文件内容如下:
"""
host = '127.0.0.1'
port = 8080
"""
import settings
def singleton(cls):
_instance = cls(settings.host, settings.port)
def wrapper(*args, **kwargs):
if args or kwargs:
return cls(*args, **kwargs)
return _instance
return wrapper
@singleton # MySQL=singleton(MySQL)
class MySQL():
def __init__(self, ip, port):
self.ip = ip
self.port = port
obj1 = MySQL('127.0.0.1', 8080)
obj2 = MySQL('127.0.0.1', 8080)
print(obj1 is obj2) # False
obj1 = MySQL()
obj2 = MySQL()
print(obj1 is obj2) # True
5. 类装饰器
# settings.py文件内容如下:
"""
host = '127.0.0.1'
port = 8080
"""
import settings
class Singleton:
_instance = None
def __init__(self, cls):
self.cls = cls
def __call__(self, *args, **kwargs):
if args or kwargs:
return self.cls(*args, **kwargs)
if not self._instance:
self._instance = self.cls(settings.host, settings.port)
return self._instance
@Singleton # MySQL=Singleton(MySQL)
class MySQL():
def __init__(self, ip, port):
self.ip = ip
self.port = port
obj1 = MySQL('127.0.0.1', 8080)
obj2 = MySQL('127.0.0.1', 8080)
print(obj1 is obj2) # False
obj1 = MySQL()
obj2 = MySQL()
print(obj1 is obj2) # True
6. 导入模块
# singleton.py文件内容如下
"""
class MySQL:
def __init__(self, host, port):
self.host = host
self.port = port
instance = MySQL('127.0.0.1', 8080)
"""
import singleton
obj1 = singleton.MySQL('127.0.0.1', 8080)
obj2 = singleton.MySQL('127.0.0.1', 8080)
print(obj1 is obj2) # False
obj1 = singleton.instance
obj2 = singleton.instance
print(obj1 is obj2) # True
三. 什么是元类?元类的应用场景有哪些,能具体说说吗?
"""
什么是元类?
python之中一切皆对象, 类也是对象. 即可调用类实例化产出对象, 那也可调用元类实例化产生类(type)
应用场景:
1. 自定义元类来控制类的产生
2. 自定义元类控制类的调用(类的对象的产生)
"""
四. 以下代码输出是什么?请给出答案并解释
class Parent:
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Child1.x = 3
print(Parent.x, Child1.x, Child2.x)
# 答案
'''
1 1 1
1 2 1
1 3 1
'''
五. 简述面相对象的三大特性及特点,其中你认为哪个特性使用频率最高,为什么?
# 面相对象的三大特性及特点
# 继承: 继承是一种新建类的方式, 新建的类可以继承一个或多个父类. 那么这个新建的类就被称之为子类或者派生类, 子类就可以继承父类的所有属性.
# 封装: 把数据与功能整合到一起
# 多态: 同一种事物有多种形态. 多态性可以在不考虑对象具体使用情况的前提下直接使用对象
# 我认为继承使用频率最高
因为我们书写新建的类继承就不需要写更多的重复代码, 并且最重要的是, 还可以完完全全继承父类的所有属性和方法
六. AOP, OOP, POP
AOP Aspect Oriented Programming 面向切面编程(装饰器)
OOP Object Oriented Programming 面向对象编程(class)
POP Process-oriented programming 面向过程编程
七. type和object的关系
# 前言: python3中所有的类都继承自object. (包括type)
# 1. type是object的类(object是由type实例化得到)
print(type(object)) # <class 'type'>
# 2. type是type的类 (CPython是基于C语言写的, 通过type的指针指向自己, 来明确自己是自己的类的关系)
print(type(type)) # <class 'type'>
# 3. type继承了object()
class type(object):
...
# 拓展: 类似于int这种内置的类, 也是由type实例化得到的, 即它们的类就是type
print(type(int)) # <class 'type'>
print(type(dict)) # <class 'type'>