写这篇博文时十分忐忑~ 且谈一下我的认识,有错的欢迎留言指正。
明确几点
Python中一切皆对象
所有的类 都继承自 object
,也就是说 object
是所有类的基类(超类)
type
也继承自 object
源码中type 的定义:class type(object):
type
是 objcet
的类型 同时 object
是 type
的超类
明确继承具有传递性。 鸡
继承了 家禽
, 家禽
又继承了 禽类
,因此鸡也属于禽类,就是这样的关系。
类和实例关系。类也是对象,在两个对象中,一个是另一个的实例。例如鸡是一个类 叫小红的鸡是鸡的实例。
在Python3中,类和类型已经是一种东西了
。
在Python3 中只有类和非类两种对象。类型是"
class Chicken(object): # 鸡类 他不仅仅是类 也是一个对象,它是 type 的对象
pass
xiaohong = Chicken() # 它是鸡类 这个类的对象
Python一切皆对象
1 在Python中 我们常说的 类
也是 对象
,而它们的类是 元类 : type
简单点易于理解称为 类的类
2 内建的类(类型),object、list、tuple、dict。
3 自定义的类 MyClass 等等任何你喜欢的名字。
4 由 自定义的类
和 内建的类
实例化的对象就是我们常说的 对象
了,也叫对象的实例。
两种关系
在面向对象的世界里有两种关系,这与语言本身没有关系,只要是面向对象的语言都拥有这样的两种属性。类型实例关系和继承关系。
类型实例关系
即该类由谁创建
str('abc') 类 str 创建了实例 abc。
class Person(object):
""" A simple Person class. """
monkey = Person()
# monkey 和 Person 就是 类型和实例的关系 type(monkey) -->
继承关系
即类继承自谁
class MyList(list):
""" A custom list class , it's a subclass of `list`. """
# MyList 就是 list 的子类, 它和list 就是 继承关系
type 和 object的关系
# 这是Python 源码中对type 的定义
class type(object):
"""
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
"""
...
# 由此 可见 type 是 object 的子类 也就是 继承关系 <1> type 继承自 object
>>> type(object)
>>> type(type)
# 上面两行代码的输出很清晰 type 和 object 以及 type 与 type 存在 类型实例关系
# <2> type 是 object 的类型
# <3> type 是 type 的类型
一个类/对象的诞生过程
类和对象的创建十分相似,类 本身也是对象~,他们由元类创建。
创建类的方法
class 关键字
关于这种方式无需赘述,如果下面的代码看不懂,那也没必要继续向下阅读了。
class MyClass(object):
"""This is a simple class for display how to create a class. """
name = 'NewClass'
def func(self):
print('Hello class, my name is %s' % self.name)
new_obj = MyClass()
print(new_obj.func)
# >
# Hello class, my name is NewClass
type函数
type
这个函数有点傻屌,它依据参数的不同拥有两种完全不同的行为,在程序设计中是很另类的,似乎也不符合Python的设计哲学。按照Python的 Style 他应该是两个函数才对,但是这是为了更好的向后兼容。
type
接受三个参数 第一个参数为类的名字, 第二个参数为继承列表, 第三个参数为属性字典(属性和方法)
def func(self):
""" A simple function to bound NewClass. """
print('Hello type, my name is %s' % self.name)
TypeClass = type('TypeClass', (object,), {'name': 'NewClass', 'func': func})
type_obj = TypeClass()
print(type_obj.func)
type_obj.func()
# >
# Hello type, my name is TypeClass
看看创建的细节
到这里我认为你已经对元类 type 有了一定的了解:
type就是Python在背后用来创建所有类的元类。包括字典 元组 字符串 类 甚至函数等等 都是由type创建。
甚至你查看object
的类型也会告诉你他是 type
但是 type
又继承自object
源码中写的很清晰。实质上他们都由虚拟机创建,同时object
的type
属性是其子类type
而type又继承object
不要问先有鸡还是先有蛋~ 你可以抽相处一个类型对象的概念,这个东西 类型是type 父类是object 当然仅仅是概念
。不要在这里纠结~ 好吧~ !
类的创建会调用两个方法, __new__ 和 __init__
。__new__
用来从类实例化 对象
__init__
负责实例化这个对象。
举个不恰当的例子,__new__
方法就相当于 生孩子,__init__
方法就相当于给这个孩子起名,上户口这样子。没有 __new__
就没法__new__
因此 __new__
方法一定在 __init__
之前 而__init__
需要 __new__
方法的结果 就是被实例化的对象(就生的那个孩子 没孩子 一切白搭) !
__call__
是个神奇的方法, 它允许用户像使用函数那样使用类或对象,也就是使用()
就回来调用__all__
。
_call_
对象通过提供 __call(slef, *args ,**kwargs)__
方法可以模拟函数的行为。即允许以类/对象() 的形式来调用。
元类的__call__
方法在继承的类进行实例化时调用(此时实例化出的是个类,而不是对象)
_new_
将自身实例化时,也就是创建对象时调用的方法,该方法是一个静态方法,第一个参数为类本身,返回值为为该对象分配的空间。也就是被创建的这个对象。__new__
方法至少需要一个cls 参数,表示的是将要被实例化的类本身,需要注意的是该方法必须返回一个空间,也就是返回实例化后的对象 return super().\__new__()
或者 object.__new__()
_init_
拿到__new__
方法返回的对象,对这个新创建出来的对象进行一些初始化操作。
优雅的控制类和对象
使用上述的一些方法我们可以优雅的控制类的创建和使用。例如 我们可以自定义元类来设计优雅的API, 虽然元类的设计麻烦,但是使用其创建的类 使用起来将会非常舒服~ 例如Django 中的model
的使用~ 真香~!
改写类来控制创建的对象
实现一个配置类,该类需要保证全局只有一个实例,并且需要保证同一时间 配置是一致的。也就是需要保证线程安全。下面是代码,通过控制 __new__
方法来实现单例。
import threading
def synchronized(bar):
""" threading lock for Config"""
bar.__lock__ = threading.Lock() # get lock
def lock_func(*args, **kwargs):
with bar.__lock__:
return bar(*args, **kwargs)
return lock_func
class Config(object):
""" Singleton `Config` ."""
_instance = None
@synchronized
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance
改写元类来控制创建的类
元类所创建的类会拥有元类拥有的方法。
通常的自定义的元类会重写 __new__
、__call__
、 __init__
。此时他们的第一个参数不再是对象,而是将要创建的类。__new__
返回的也将是类, 而 __init__
是添加类属性而不是实例属性。
假设上一步的操作中需要将配置类中所有的属性都变为大写的。以 _
开头的属性除外,要怎么做呢?
将函数作为元类
假设上一步的操作中需要将配置类中所有的属性都变为大写的。以 _
开头的属性除外,要怎么做呢?
import threading
def synchronized(bar):
""" threading lock for Config"""
bar.__lock__ = threading.Lock() # get lock
def lock_func(*args, **kwargs):
with bar.__lock__:
return bar(*args, **kwargs)
return lock_func
def filter_config(cls_name, cls_mro, cls_attr):
cls_attr = {k.upper(): v for k, v in cls_attr.items() if not k.startswith('_')}
return type(cls_name, cls_mro, cls_attr) # 返回一个类
class Config(metaclass=filter_config): # 指定元类
""" Singleton `Config` ."""
_instance = None
@synchronized
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance
number = 100
config = Config()
print(config.NUMBER) # 100
将类作为元类
import threading
def synchronized(bar):
""" threading lock for Config"""
bar.__lock__ = threading.Lock() # get lock
def lock_func(*args, **kwargs):
with bar.__lock__:
return bar(*args, **kwargs)
return lock_func
class Filter_config(type):
def __new__(cls, cls_name, cls_mro, cls_attr):
cls_attr = {k.upper(): v for k, v in cls_attr.items() if not k.startswith('_')}
return super(Filter_config, cls).__new__(cls, cls_name, cls_mro, cls_attr)
class Config(metaclass=Filter_config): # 指定元类
""" Singleton `Config` ."""
_instance = None
@synchronized
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance
number = 100
config = Config()
print(config.NUMBER) # 100