[初学python]新类(new-style class)

原创 2004年08月04日 20:08:00

类(class)也是对象
在python之中,万物皆对象。类也是对象。“类的类”就被称为元类(即类是元类的实例)。正如类的实例的行为取决于类,元类的实例(类)的行为也取决于元类。

new-style classes的由来
new-style classes是python在2.2版本所加入的一个重要特性。所有的内建类型都是new-style classes。引入new-style classes,就是为了逐步弥合python中内建类型和classic classes之间的鸿沟。至此,内建类型终于可以和classic classes一样,在定义类时作为基类被继承。但在完全统一之前,他们之间仍然存在巨大差别。其根本原因是他们各自的元类不同:classic classes的元类是types.ClassType,而new-style classes的元类是type。
换句话说,我们可以做出这样的定义:元类为types.ClassType的类是classic classes;元类为type的类是new-style classes。
另外,根据后面的结论,我们还可以预先给出new-style classes的另一种定义:object和所有直接或间接以它为基类的类是new-style classes。这里的object是一个new-style class的内建类型, 它作为所有new-style classes的
一个公共基类(详见下文)。

new-style classes的创建
python的类对象,直接由class语句生成。
那么,class语句是怎样确定它所要生成的类对象的元类的呢?这个问题的答案,可以从class语句的工作原理中得出:
解释器通过执行class语句,首先获得三方面的信息:类名,类的基类,类的属性和方法。
其中类的基类被放入一个tuple中,类的属性和方法被放在一个dict中。
接着,解释器就可以通过这些信息来确定元类了:
 .如果类属性中有“__metaclass__”,那么它所绑定的对象就是元类
 .否则,如果类定义了基类,那么就使用基类的元类(只要基类中有new-style classes,那么元类就为type )
 .否则,如果类所在的模块中有"__metaclass__"这样一个名字,它所绑定的对象就是元类
 .否则,类的元类就被默认为types.ClassType
确定了元类,解释器就把类名、类的基类(tuple)、类的方法和属性(dict)作为初始化参数传给元类,以生成该元类的一个实例(即是类)。
最后,解释器将类名与生成的类对象绑定在一起。
所有其它的内建类型(即非object),就是通过继承一个公共的new-style基类object,而成为new-style classes的。
由上面的叙述,我们可以得出创建一个new-style class的方法,共三种:
1.继承一个内建类型
>>> class MyDict(dict):
 pass
>>> type(MyDict)
<type 'type'>
2.设定类的__metaclass__属性
>>> class MyNewStyle1:
 __metaclass__ = type
>>> type(MyNewStyle)
<type 'type'>
3.设定一个模块级的__metaclass__
>>> __metaclass__ = type
>>> class MyNewStyle2:
 pass
>>> type(MyNewStyle2)
<type 'type'>
还有一点值得注意,不管用以上哪种方式创建的new-style classes都最终会直接或间接地以object做为基类(这里就体现了元类对类的控制)。
也就是说,即使如方法2,3那样没有直接写出继承语法,object也会成为基类:
>>> MyNewStyle1.__bases__
(<type 'object'>,)
>>> MyNewStyle2.__bases__
(<type 'object'>,)
当然,如果上面提出的创建new-style classes的条件都不满足,就会创建一个原来的classic class
>>> del __metaclass__ #消除前面引入的模块级的影响
>>> class MyClassic:
 pass
>>> type(MyClassic)
<type 'classobj'>
>>> MyClassic.__bases__
()

new-style classes的使用
new-style classes提供了一些新的特殊方法,让我们可以更好地控制类的行为。
下面,我们讲几个常用的:
1.__new__:
  __init__用来控制类的实例的初始化,而__new__控制初始化之前的行为---也就是实例的生成。
  因此__new__的第一个参数是类(cls),而不是self。__new__的任务是返回一个所传入参数类(cls)的实例。
  但,真正能够生成一个new-style class的实例的,只有object.__new__。因此我们定义的__new__,在需
  要生成实例时,就应该调用它。
  利用__new__的这个特性,我们可以很容易实现Singleton Pattern,让我们的类只会产生一个唯一的对象
>>> class Singleton(object):
 __instance = None
 def __new__(cls, *args, **kwd):
  if Singleton.__instance is None:
   Singleton.__instance = object.__new__(cls, *args, **kwd)
  return Singleton.__instance
>>> class MyClass(Singleton):
 pass

>>> a = MyClass()
>>> b = MyClass()
>>> a is b
True
>>> a is b is Singleton._Singleton__instance
True 
  通过继承,就可以使我自定义的类的行为符合Singleton Pattern的要求
 
2.__getattribute__:
  __getattribute__比__getattr__对使用“.语法”(如obj.a)进行对象的属性和方法的读取操作提供了更强大的控制。
  任何obj.a,都会被直接转化为obj.__getattribute__(a),包括__dict__。因此,在__getattribute__的实现,我们
  不能直接用使用__dict__(那会造成循环调用),而应该的把真正的读取操作交给object.__getattribute__。
>>> class MyClass(object):
 def __getattribute__(self, name):
  print "accessing", name
  return object.__getattribute__(self, name)

 
>>> a = MyClass()
>>> a.__dict__
accessing __dict__
{}

3.__get__,__set__,__delete__:
  重载这三个方法,可以实现对类属性的读写控制
class RevealAccess(object):
    """A data descriptor that sets and returns values
       normally and prints a message logging their access.
    """

    def __init__(self, initval=None, name='var'):
        self.val = initval
        self.name = name

    def __get__(self, obj, objtype):
        print 'Retrieving', self.name
        return self.val

    def __set__(self, obj, val):
        print 'Updating' , self.name
        self.val = val

>>> class MyClass(object):
    x = RevealAccess(10, 'var "x"')
    y = 5

>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
>>> m.x = 20
Updating var "x"
>>> m.x
Retrieving var "x"
20
>>> m.y
5
  可以用内建函数property,简化上述步骤
>>> class MyClass(object):
 def __init__(self):
  self.__x = 1
 def getx(self):
  print "Retrieving x"
  return self.__x
 def setx(self, value):
  print "Updating x"
  self.__x = value
 def delx(self):
  print "Deleting x"
  del self.__x
 x = property(getx, setx, delx, "I'm the x property")
 
>>> m = MyClass()
>>> m.x
Retrieving x
1
>>> m.x = 2
Updating x
>>> del m.x
Deleting x


关于新类的更多特性和使用方法,请参考
Unifying types and classes in Python 2.2
How-To Guide for Descriptors

后记
我也是一名python初学者,把自已学习中的困惑与收获记录下来,与大家交流,希望能得到大家的意见。


 

 

转载:Python中的new style class机制实现

1.Python中的对象模型python中所有东西都是对象 class对象:表示Python内置的类型和定义的类型instance对象(实例对象):表示由class对象创建的实例 1.1 对象间的...
  • alwaysxihe
  • alwaysxihe
  • 2015年05月07日 15:14
  • 433

python 老式类old style class和新式类new style class,类的单例模式

新式类new style class
  • ws_cs_dn
  • ws_cs_dn
  • 2014年07月11日 19:10
  • 1060

Python新式类和旧式类的区别

新式类是为了统一**而在2.2中开始引入的。 我使用的是2.6。 上面的例子比较明白的说明了问题。 B是定义的新式类。那么输入b的时候,不论是type(b),还是b.__class__都是输...
  • imzoer
  • imzoer
  • 2013年03月06日 22:08
  • 11987

python 新式类和旧式类

python的新式类是2.2版本引进来的,我们可以将之前的类叫做经典类或者旧类。      为什么要在2.2中引进new style class呢?官方给的解释是:  为了统一类(class)和类...
  • jb19900111
  • jb19900111
  • 2014年03月01日 18:31
  • 6240

Python新式类和经典类的区别

从Python2.2开始,Python 引入了 new style class(新式类) 新式类跟经典类的差别主要是以下几点: 新式类对象可以直接通过__class__属性获取自身...
  • u010066807
  • u010066807
  • 2015年07月15日 18:04
  • 6967

python中的 new-style class 及其实例详解

1.1. 5.2 new-style Class 及其实例 前面我提到 python 2.2 中引入了 new-style 对象模型. new-style class 及其实例与 Class...
  • wh62592855
  • wh62592855
  • 2011年11月01日 22:18
  • 1919

Python 经典类和新式类 super用法 (四)

在Python2.x的2.2以上版本中,新式类是继承object的类。 经典类的MRO(基类搜索顺序)算法是深度优先。 新式类的MRO算法是C3算法。 经典类 class A:pass clas...
  • xhw88398569
  • xhw88398569
  • 2015年09月22日 22:21
  • 2021

[译]2.Python扩展外置模块定义新类型——类型方法

隐藏] 2.2.1. 结束和内存回收 2.2.2 对象描述 2.3.3. 属性管理 2.2.3.1 通常属性管理 2.2.3.2 指定类型属性管理 2.2.4 对象比较...
  • linuxarmsummary
  • linuxarmsummary
  • 2015年07月07日 17:35
  • 1113

Python中__new__()方法的使用和实例化

new()是在新式类中新出现的方法,它作用在构造方法init()建造实例之前,可以这么理解,在Python 中存在于类里面的构造方法init()负责将类的实例化,而在init()调用之前,new()决...
  • Four_Infinite
  • Four_Infinite
  • 2016年10月12日 17:35
  • 4726

python中__init__()方法和__new__()方法的区别

下面先通过一段代码看看这两个方法的调用顺序:#!/usr/bin/env pythonclass A(object): def __init__(self,*args,**kwargs): ...
  • Four_Infinite
  • Four_Infinite
  • 2016年10月13日 14:19
  • 2770
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[初学python]新类(new-style class)
举报原因:
原因补充:

(最多只允许输入30个字)