参考博客:Python面向对象、魔法方法原博连接
本文只归纳魔法方法中的简单几个,详细的请参考原博。
一、python面向对象的三大特征
此处暂时不展开详细解释,日后另附文详述
1、继承
继承是从已有类得到继承信息创建新类的过程,一方面可以继承父类所有的属性和方法,另一方面可以增加或则重写父类方法,以适应具体业务流程。
2、封装
封装就是把数据和操作数据的方法绑定起来,通过已定义的接口实现对数据的访问以及修改,屏蔽繁杂的技术细节。编写一个类就是对数据和数据操作的封装,可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口
3、多态
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态,多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
在动态语言中经常提到鸭子类型,所谓鸭子类型就是:If it walks like a duck and quacks like a duck, it must be a duck。鸭子类型是编程语言中动态类型语言中的一种设计风格,一个对象的特征不是由父类决定,而是通过对象的方法决定的。
二、python中的特殊方法和魔法方法
1、特殊方法
__XXX
该类变量是一个私有变量(private),只有内部可以访问,外部不能访问。
XXX
该类变量是特殊变量,特殊变量是可以直接访问的,不是private。
变量。
MasterStudent(obj).__doc__ # 类注释
MasterStudent(obj).__name__ # 类名(可能带命名空间)
MasterStudent(obj).__bases__ # 直接父类
MasterStudent(obj).__dict__ # 类信息,字典类型
MasterStudent(obj).__class__ # 一般实例调用__class__属性时会指向该实例对应的类,然后可以再去调用其它类属性(注意是类属性,不是实例属性)
MasterStudent(obj).__module__ # 模块名
_XXX
该类变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思
就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
XXX_
定义的一个变量和某个保留关键字冲突,这时候可以使用单下划线作为后缀, 以示区分。
2、魔法方法
init(),del(),new()
验证一下这三个方法的执行顺序
class A(object):
def __init__(self):
print('__init__')
def __new__(cls, *args, **kwargs):
print('__new__')
return super().__new__(cls, *args, **kwargs) # cls表示一个类,一个当前要被实例化的类,参数由py解释器自动提供
def __del__(self):
print('__del__')
a = A()
print('do something')
# __new__
# __init__
# do something
# __del__
# 实际上,__new__()负责创建一个对象,__init__负责定制化该对象,即是在对象创建好之后初始化变量
new()单例应用
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
"""
注意这实际上是一个类方法, cls 表示当前类
:param args:
:param kwargs:
:return:
"""
if cls._instance is None:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
s1 = Singleton()
s2 = Singleton()
if s1 is s2:
print('yeah')
getitem(),setitem(),delitem()
getitem()将对象当作list使用,如obj = ACLASS(), obj_first=obj[0]
setitem()将对象当作dict使用,如obj = ACLASS(),obj[key] =value
class A(object):
def __init__(self):
self['B'] = "BB"
self['D'] = "DD"
self.jj = 'jj'
del self['D']
def __setitem__(self, name, value):
"""
每当属性被赋值的时候都会调用该方法
"""
print("__setitem__:Set %s Value %s" % (name, value))
self.__dict__[name] = value
def __getitem__(self, name):
"""
当访问属性时会调用该方法
"""
print("__getitem__:Try to get attribute named '%s'" % name)
if hasattr(self, name):
return getattr(self, name)
return None
def __delitem__(self, name):
"""
当删除属性时调用该方法
"""
print("__delitem__:Delect attribute '%s'" % name)
del self.__dict__[name]
print(self.__dict__)
if __name__ == "__main__":
X = A()
b = X['jj']
print(b)
enter(),exit()
这两个魔法方法使对象是用于With会话管理,一般用于需要打开关闭的场景,如文件读写、数据库连接。
#! /usr/bin/python
# _*_ coding: utf-8 _*_
class OpenTextFile(object):
"""
实现打开一个文件使用with,这里仅仅是个例子
因为 open()本身就可以实现 with context
"""
def __init__(self, file_path):
self.file = file_path
def __enter__(self):
self.f = open(self.file, 'r', encoding='utf-8')
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
with OpenTextFile('./with_context.py') as f:
print(f.readlines())
call()
假设有对象obj, 则obj()可以调用__call__()方法
class A(object):
def _pre_process(self):
print('preoprocess data')
def __call__(self, *args, **kwargs):
self._pre_process()
print('object called over')
A()() # 调用了类中__call__()中的逻辑