在python中,类型和类型的区别是什么?

在python中,类型和类型的区别是什么?,python,types,new-operator,metaclass,Python,Types,New Operator,Metaclass,我在写一个元类,不小心这样做了: class MetaCls(type): def __new__(cls, name, bases, dict): return type(name, bases, dict) class MetaCls(type): def __new__(cls, name, bases, dict): return type.__new__(cls, name, bases, dict) MyClass = MyMeta

我在写一个元类,不小心这样做了:

class MetaCls(type):
    def __new__(cls, name, bases, dict):
        return type(name, bases, dict)
class MetaCls(type):
    def __new__(cls, name, bases, dict):
        return type.__new__(cls, name, bases, dict)
MyClass = MyMeta.__new__(MyMeta, cls, bases, attributes)
meta_class = MyClass.__metaclass__
meta_class.__init__(MyClass, cls, bases, attributes)
return MyClass
…而不是像这样:

class MetaCls(type):
    def __new__(cls, name, bases, dict):
        return type(name, bases, dict)
class MetaCls(type):
    def __new__(cls, name, bases, dict):
        return type.__new__(cls, name, bases, dict)
MyClass = MyMeta.__new__(MyMeta, cls, bases, attributes)
meta_class = MyClass.__metaclass__
meta_class.__init__(MyClass, cls, bases, attributes)
return MyClass

这两个元类之间到底有什么区别?更具体地说,是什么导致第一个类不能正常工作(某些类没有被元类调用)?

描述得很好

如果没有返回正确类型的对象,那么定义自定义元类就没有意义

return type(name, bases, dict)
您从中得到的是一个新的
类型
,而不是一个
MetaCls
实例。因此,
MetaCls
(包括
\uuuu init\uuuu
)中定义的方法永远无法调用


type.\uuuuu new\uuuuu
将作为创建新类型的一部分被调用,是的,但是进入该函数的
cls
的值将是
type
而不是
MetaCls
,在第一个示例中,您正在创建一个全新的类:

>>> class MetaA(type):
...     def __new__(cls, name, bases, dct):
...         print 'MetaA.__new__'
...         return type(name, bases, dct)
...     def __init__(cls, name, bases, dct):
...         print 'MetaA.__init__'
... 
>>> class A(object):
...     __metaclass__ = MetaA
... 
MetaA.__new__
>>> 
在第二种情况下,您正在调用父级的
\uuuu new\uuuu

>>> class MetaA(type):
...     def __new__(cls, name, bases, dct):
...         print 'MetaA.__new__'
...         return type.__new__(cls, name, bases, dct)
...     def __init__(cls, name, bases, dct):
...         print 'MetaA.__init__'
... 
>>> class A(object):
...     __metaclass__ = MetaA
... 
MetaA.__new__
MetaA.__init__
>>> 
实现相同结果的另一种方法:

cls = "MyClass"
bases = ()
attributes = {'foo': 'bar'}
MyClass = MyMeta(cls, bases, attributes)
MyMeta
是可调用的,因此Python将使用特殊的方法
\uuuuuuu调用\uuuuuu

Python将在
MyMeta
的类型中查找
\uuuuuu调用
(在我们的例子中是
type

对于新样式的类,特殊方法的隐式调用是 只有在对象的类型上定义时才能保证正常工作,而不是 在对象的实例字典中“

MyClass=MyMeta(…)
被解释为:

my_meta_type = type(MyMeta)
MyClass = my_meta_type.__call__(MyMeta, cls, bases, attributes)
类型中。\uuu call\uuuu()
我想象如下:

class MetaCls(type):
    def __new__(cls, name, bases, dict):
        return type(name, bases, dict)
class MetaCls(type):
    def __new__(cls, name, bases, dict):
        return type.__new__(cls, name, bases, dict)
MyClass = MyMeta.__new__(MyMeta, cls, bases, attributes)
meta_class = MyClass.__metaclass__
meta_class.__init__(MyClass, cls, bases, attributes)
return MyClass
MyMeta.\uuuuu new\uuuuuu()
将决定如何构建
MyClass

type.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


type(cls、base、attributes)
将为
MyClass
设置默认元类(即type),请参考下面的注释,希望这有帮助

class MetaCls(type):
    def __new__(cls, name, bases, dict):
        # return a new type named "name",this type has nothing
        # to do with MetaCls,and MetaCl.__init__ won't be invoked
        return type(name, bases, dict)

class MetaCls(type):
    def __new__(cls, name, bases, dict):
        # return a new type named "name",the returned type 
        # is an instance of cls,and cls here is "MetaCls", so 
        # the next step can invoke MetaCls.__init__ 
        return type.__new__(cls, name, bases, dict)

首先需要弄清楚
对象是如何工作的

这是下面的内容:

object.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

调用以创建类
cls
的新实例<代码>\uuuu new\uuuuu()是一个静态 采用 请求实例作为其第一个参数的类。 其余参数是传递给对象构造函数的参数 表达式(对类的调用)。
\uuuu new\uuuu()的返回值
应该是新对象实例(通常是
cls
的实例)

典型的实现通过调用 超类的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()方法使用
super(currentclass,cls)。\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
在返回新创建的实例之前,请根据需要将其删除

如果
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
已传递给
\uuuu new\uuuu()

如果
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

\uuuu new\uuuu()
主要用于允许不可变类型的子类(如
int
str
tuple
)自定义实例创建。也是 通常在自定义元类中重写以自定义类 创造


因此,在mg's中,前者不调用函数
\uuuu init\uuuuu
,而后者在调用
\uuu new\uuuuuu

后调用函数
\uuuu init\uuuuu
,但这就是我想问的问题:为什么
键入的对象不正确?我知道我必须使用子类的
\uuu new\uuu
方法,但是这与使用
类型有什么不同?类型如何神奇地知道你想要它生成什么类型的对象?因为我告诉了它。我输入了名称、基数和dict。我还需要提供哪些其他信息?类型是如何与对象相关的?我没有得到那部分。OP问的是关于
类型的问题。它创建了一个类,而不是
对象。它创建了一个类的实例。请看关于类类型(对象)的文档,我想这可能是类型和对象之间的关系。如果你明白了,记得取消你的否决票,谢谢!您(@Nishant,@rlat)需要弄清楚的是Python的类型和对象是什么,下面是答案;因此类型之间没有区别。与对象相关。对于python3
类A(对象,元类=MetaA):pass
。class A作用域中的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但这里你指的是类名。