python中一切皆对象
1. 名词解释
- 类: 类是一个抽象的概念,是一系列对象中相似特征与技能的结合体,不存在某一个对应的实体
- 对象:是类实例化的结果, 是一个实际存在的事物,通过对象可以找到一个固定的个体
- 父类: 类存在继承的特性, 类可以继承父类, 并继承其中的方法与属性, python3中都是新式类,不写明时都是继承自 object基类
- 元类: python中一切皆对象, 类本身也是对象, 元类就是用来生成类的类
2. 名称空间的访问顺序
前提:我们平时调用方法与属性时, 通常是通过 类生成的对象 来调用的
- 普通对象的名称空间 -> 类的名称空间 -> 根据mro列表查找父类的名称空间
上方需要说明的是:
- 我们平时会根据类生成对象, 然后通过对象来调用方法与属性
- 此时我们首先会访问对象的名称空间, 然后访问类的名称空间, 然后访问父类的名称空间
- 此过程并不会访问元类的名称空间, 因为对象只能向上访问到类及父类的名称空间
然而
- 我们会想,不是会访问类的名称空间嘛? 元类也是类, 为什么不会访问到呢?
- 那是因为: 元类是类的类, 而不是对象的类, 只有我们通过 【类.方法】 访问方法时, 才会先访问类自己的名称空间, 然后再访问元类的名称空间, 因为元类 是 类的类
3. __init__
, __new__
, __call__
前提: 类实例化对象时分为两步:1. 通过类的
__new__
方法生成一个空的对象 2. 通过类的__init__
方法来初始化对象
-
__init__
: 是用来对象初始化的, 通过__init__
中的方法,可以初始化对象中独特的属性, 生成对象自己的名称空间 -
__new__
: 是用来生成空的对象的, 我们听其他语言说的new一个新对象可以辅助我们理解
1. 在生成对象时, 首先会调用 类的 __new__方法, 生成一个空的对象
class TestClass: ## 基础的单例模式
obj = None
def __new__(cls, *args. **kwargs):
if cls.obj:
return cls.obj
else:
cls.obj = super().__new__(cls, *args, **kwargs)
return cls.obj
a = TestClass()
b = TestClass()
print(a) ## <__main__.TestClass object at 0x000001F2BC04ACD0>
print(b) ## <__main__.TestClass object at 0x000001F2BC04ACD0>
2. 然后调用对象的 __init__方法, 进行对象的初始化
-
__call__
: 此方法用来表示对象是否可执行, 对象会调用类的__call__
方法, 如果类存在此方法, 就可以调用, 不存在就不可以调用, 决定类是否可以被调用
的方法是元类的__call__
方法
class TestClass:
def __init__(self, name):
self.name = name
def __call__(self):
return self.name
lee = TestClass('lee') # 不会打印
andy = TestClass('andy') # 不会打印
lee() # lee
andy() # andy
4. 自定义元类
我们如果想要控制类的生成, 可以自定义元类
class MetaClass(type): # 继承自元类
def __init__(cls, class_name, bases, dict): # 此处无法修改dict内的值
cls.name = 'andy' # 此方式可以为类增加属性
if not class_name.istitle():
super().__init__(class_name, bases, dict)
else:
raise valueError('class name is not valid')
def __new__(cls, class_name, bases, dict):
dict['__author__'] = 'lee' # 为类增加属性
return super().__new__(cls, class_name, bases, dict)
其中:
- class_name, bases, dict 是三个固定不必须要传入的参数
- class_name: 类的名字
- bases: 类的父类们
- dict: 类的名称空间
class FromMetaClass(metaclass=MetaClass):
def __init__(self):
pass
print(FromMetaClass.__dict__)
# {'__module__': '__main__',
# '__init__': <function FromMetaClass.__init__ at 0x0000029F8C9083A0>,
# '__author__': 'lee',
# '__dict__': <attribute '__dict__' of 'FromMetaClass' objects>,
#'__weakref__': <attribute '__weakref__' of 'FromMetaClass' objects>,
#'__doc__': None,
#'name': 'andy'}