写这篇博文时十分忐忑~ 且谈一下我的认识,有错的欢迎留言指正。

明确几点

Python中一切皆对象

所有的类 都继承自 object,也就是说 object 是所有类的基类(超类)

type 也继承自 object 源码中type 的定义:class type(object):

type 是 objcet 的类型 同时 object 是 type 的超类

明确继承具有传递性。鸡 继承了家禽 ,家禽 又继承了禽类 ,因此鸡也属于禽类,就是这样的关系。

类和实例关系。类也是对象,在两个对象中,一个是另一个的实例。例如鸡是一个类 叫小红的鸡是鸡的实例。

在Python3中,类和类型已经是一种东西了。

在Python3 中只有类和非类两种对象。类型是"" 那么它是类否则它是非类。听起来很绕,英文原文:There are only two kinds of objects in Python: to be unambiguous let's call these types and non-types. Non-types could be called instances, but that term could also refer to a type, since a type is always an instance of another type. Types could also be called classes, and I do call them classes from time to time.

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