Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么元类定义改变了经典类的mro?_Python_Python 2.7_Method Resolution Order - Fatal编程技术网

Python 为什么元类定义改变了经典类的mro?

Python 为什么元类定义改变了经典类的mro?,python,python-2.7,method-resolution-order,Python,Python 2.7,Method Resolution Order,根据: 经典类使用了一个简单的MRO方案:在查找方法时, 基类是使用从左到右的简单深度优先搜索的 计划 这可以在Python2.6中验证 In [1]: import sys In [2]: sys.version Out[2]: '2.6.6 (r266:84292, Jul 23 2015, 15:22:56) \n[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)]' In [3]: class D: def f(self): return 'D'

根据:

经典类使用了一个简单的MRO方案:在查找方法时, 基类是使用从左到右的简单深度优先搜索的 计划

这可以在Python2.6中验证

In [1]: import sys

In [2]: sys.version
Out[2]: '2.6.6 (r266:84292, Jul 23 2015, 15:22:56) \n[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)]'

In [3]: 
class D:
    def f(self): return 'D'
class B(D): pass
class C(D):
    def f(self): return 'C'
class A(B, C): pass
   ...: 

In [4]: A().f()
Out[4]: 'D'
但是,如果我定义了一个元类,我在Python 2.7.12中得到了一个不同的结果:

Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
Type "copyright", "credits" or "license" for more information.

IPython 5.4.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: class D:       # Note: Old-style
   ...:     def f(self): return "D.f()"
   ...: class B(D): pass
   ...: class C(D):
   ...:     def f(self): return "C.f()"
   ...: class A(B, C): pass
   ...: 

In [2]: A().f()
Out[2]: 'D.f()'    # It works as expected.

In [3]: class __metaclass__(type):
   ...:     "All classes are metamagically modified to be nicely printed"
   ...:     __repr__ = lambda cls: cls.__name__
   ...:     

In [4]: class D:       # Note: Old-style
   ...:     def f(self): return "D.f()"
   ...: class B(D): pass
   ...: class C(D):
   ...:     def f(self): return "C.f()"
   ...: class A(B, C): pass
   ...: 

In [5]: A().f()
Out[5]: 'C.f()'   # WTF??

元类仅适用于新样式的类,并且通过在类主体中具有名为
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。具有
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

class J:
  pass
class K(object):
  pass
class L:
  __metaclass__ = type

type(J) # <type 'classobj'>
type(K) # <type 'type'>
type(L) # <type 'type'>

元类仅适用于新样式的类,并且通过在类主体中具有名为
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。具有
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

class J:
  pass
class K(object):
  pass
class L:
  __metaclass__ = type

type(J) # <type 'classobj'>
type(K) # <type 'type'>
type(L) # <type 'type'>

我无法在
2.7.14[GCC 4.2.1兼容的Apple LLVM 9.0.0(clang-900.0.37)]
(Mac OSX)、
2.7.13(默认,2017年1月19日,14:48:08)\n[GCC 6.3.0 20170118]
(Debian 9.0)或
2.7.12(默认,2016年11月19日,06:48:10)\n[GCC 5.0 20160609]
(Ubuntu 16.04,看起来与您运行的版本完全相同)。结果总是
D.f()
。只有当我使用新样式的类时,它们才会报告
C.f()
@birryrree很抱歉我提出了一个误导性的问题。我发现我的结果是由于元类之前的定义。我已经修改了这个问题。我无法在
2.7.14[GCC 4.2.1兼容的Apple LLVM 9.0.0(clang-900.0.37)]
(Mac OSX),
2.7.13(默认,2017年1月19日,14:48:08)中的任何一个上重现你的2.7行为\n[GCC 6.3.0 20170118]
(Debian 9.0)或
2.7.12(默认值,2016年11月19日06:48:10)\n[GCC 5.4.0 20160609]
(Ubuntu 16.04,看起来与您运行的版本完全相同)。结果总是
D.f()
。只有当我使用新样式的类时,它们才会报告
C.f()
@birryrree很抱歉我的问题有误导性。我发现我的结果是由于元类的先前定义。我已经修改了这个问题。