V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
saximi
V2EX  ›  Python

请大家指点

  •  
  •   saximi · 2017-07-10 19:50:33 +08:00 · 1498 次点击
    这是一个创建于 2697 天前的主题,其中的信息可能已经有所发展或是发生改变。
    class MyType(type):
    def __init__(self, what, bases=None, dict=None):
    print('call myType.__init__()')
    print("class name:"+what)
    print("class bases:"+str(bases))
    print("class attributions:"+str(dict))
    super().__init__(what, bases, dict)
    def __new__(cls, name, bases, attrs):
    print("call MyType.__new__()")
    return type.__new__(cls, name, bases, attrs)
    class Foo(object):
    __metaclass__ = MyType #语句 1
    def __init__(self, name=None):
    self.name = name
    print("Foo.__init__ self=", self)
    print("Foo self.name=", self.name)
    def __new__(cls, *args, **kwargs):
    print("Foo.__new__ cls=", cls)
    return(object.__new__(cls, *args, **kwargs))
    def __call__(self, cls):
    print("Foo.__call__ cls=", cls)
    print("Foo.__call__ self=", self)
    def func(self):
    print('function is there')
    class studen(Foo):
    print("studen(Foo)") #语句 2
    def __init__(self, name=None):
    print("studen.__init__ self=", self)

    class Foo2(object):
    """docstring for Foo2"""
    def __init__(self):
    print('Foo2.__init__ self.__class__=', self.__class__)
    print("Foo2.__init__ type(self)=", type(self))

    if __name__ == '__main__':
    print("---------test1---------") #语句 3
    obj2=Foo() #语句 4
    print("---------test2---------")
    print("test2 type=", type(studen()))
    print("---------test3---------")
    print("test3 type=", type(Foo2()))

    上面这段代码的输出如下:
    studen(Foo)
    ---------test1---------
    Foo.__new__ cls=
    Foo.__init__ self= <__main__.Foo object at 0x01C2A270>
    Foo self.name= None
    ---------test2---------
    Foo.__new__ cls=
    studen.__init__ self= <__main__.studen object at 0x01C2A350>
    test2 type=
    ---------test3---------
    Foo2 self.__class__=
    Foo2 type(self)=
    test3 type=



    我的问题如下:
    1、为何语句 2 会在语句 3 之前先执行了?是不是因为类定义中的不在__new__()、__init__()和__call__()的方法之内的语句都会在模块被加载的时候立即执行?
    2、在语句 1 中,我已经指定 Foo 类要由 MyType 类来实例化创建,为何执行语句 4 的时候,类 MyType 定义中的__new__()和__init__()方法都没有被首先执行?

    恳请指点,感谢!
    4 条回复    2017-07-15 14:47:56 +08:00
    zhusimaji
        1
    zhusimaji  
       2017-07-11 16:57:47 +08:00
    给楼主贴上我自己 python2 改造后的代码
    https://gist.github.com/zhusimaji/31fe157b62703923bf6177f05f0fdbac
    依次回答楼主的问题
    ( 1 )类被倒入加载时,print 没有放在类定义的函数中是会被运行打印
    ( 2 )语句 4 -> metaclass 是__new__和__init__都是先运行,没有任何问题
    zhusimaji
        2
    zhusimaji  
       2017-07-11 16:59:47 +08:00
    这个可能与 python3 有关,建议楼主看下 python 3 关于 type 的说明
    saximi
        3
    saximi  
    OP
       2017-07-12 20:12:31 +08:00
    @zhusimaji 非常感谢啊!
    但是关于第二个问题的回答“语句 4 -> metaclass 是__new__和__init__都是先运行,没有任何问题”我还是没明白。
    在语句 1 中已经指定 Foo 类要由 MyType 类来实例化创建,所以我觉得执行“ obj2=Foo()”这个语句时,应该就是实例化了一个类 Foo 的对象并赋值给 obj2,但是要根据 MyType 的定义来实例化。
    这时应该去执行 MyType 定义中的__new__和__init__,而不是去执行 Foo 定义中的__new__和__init__。我这个理解错在哪里呢?

    另外,您修改后的代码在 PYTHON2 下运行,在类被加载时会先去执行 MyType 中的__new__和__init__,然后再执行语句 3。 但是为何在 PYTHON3 下,类被加载时不会执行 MyType 中的语句,而是直接就执行语句 3 呢?
    saximi
        4
    saximi  
    OP
       2017-07-15 14:47:56 +08:00
    自己再顶一下,上面说的遗留的问题,还请大家不吝赐教,感谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5937 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 02:57 · PVG 10:57 · LAX 18:57 · JFK 21:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.