1 类亦为对象
class Person():
name = "Rocky"
age = 18
def __init__(self, weight):
self.weight = weight
In[5]: person = Person(48)
In[6]: print(person)
<__main__.Person object at 0x00000277A5FC8DA0>
In[7]: print(Person)
<class '__main__.Person'>
In[8]: isinstance(person, Person)
Out[8]: True
一般情况下,我们称Person为类(class),通过Person(48)实例化的person为对象(object);二者之间的关系为:person是Person的实例,即Person可以创建person
然而在OOP的世界里,万事皆对象,其中也包括class,那么又是谁创造了class呢?
In[9]: Person.__class__
Out[9]: type
In[10]: isinstance(Person, type)
Out[10]: True
In[12]: type.__class__
Out[12]: type
In[13]: isinstance(type, type)
Out[13]: True
没错,正是type
2 对象的性质
既然类是对象,那么它理应有对象的特质:
- 赋值给变量
- 支持复制
- 增加属性
- 充当方法的参数
In[17]: Man = Person
In[18]: man = Man(48)
In[19]: print(man)
<__main__.Person object at 0x00000277A5FF3048>
In[20]: Man.sex = "male"
In[25]: import copy
In[26]: Man_copy = copy.copy(Man)
In[27]: print(Man_copy)
<class '__main__.Person'>
所以类属性、类方法从某种意义上讲,依然是对象的属性、对象的方法
3 创建类对象
类是type的实例,那看看type是如何创建类的
对于type的用法,可以偏向于type(person)
,查看对象的类型,显然这并不是创建类的正确方式
class type(object):
def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
"""
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
# (copied from class doc)
"""
pass
type(name, bases, dict) -> a new type
正是我们寻找的方法
其中name表示类对象名称,bases表类继承的父类(tuple),dict表示类的属性和方法的映射
# 使用type重新创建Person类
def __init__(self, weight):
self.weight = weight
Person = type("Person", (), {'name':"Rocky", 'age':18, '__init__': __init__})
4 自定义metaclass
首先看一下metaclass在python3中的使用:
class Person(object, metaclass=something):
pass
# 在python2中是使用__metaclass__属性
比如,我们希望将类的属性转换成大写
from inspect import isfunction
class Base(type):
# @classmethod
# def __prepare__(metacls, cls, bases):
# return dict()
def __new__(metacls, cls, bases, namespace):
upper_namespace = {}
for k, v in namespace.items():
if not isfunction(v) and not k.startswith('__'):
upper_namespace[k.upper()] = v
else:
upper_namespace[k] = v
return super().__new__(metacls, cls, bases, upper_namespace)
class Person(metaclass=Base):
name = "Rocky"
age = 18
def __init__(self, weight):
self.weight = weight
if __name__ == "__main__":
print(Person.__dict__)
# {'__module__': '__main__', 'NAME': 'Rocky', 'AGE': 18, '__init__': <function Person.__init__ at 0x000001D804B16598>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
关于metaclass的应用,可以参考Django中的ModelBase
网友评论