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
explist
V2EX  ›  Python

描述器类中__get__()的疑问

  •  
  •   explist · 2016-11-30 00:21:16 +08:00 · 1478 次点击
    这是一个创建于 2945 天前的主题,其中的信息可能已经有所发展或是发生改变。

    import types

    from functools import wraps

    class profiled:

    def __init__(self,func):
        wraps(func)(self)    
     
    def __call__(self,*a,**k):
        print("profiled.call")        
        return self.__wrapped__(*a,**k)
    
    def __get__(self,instance,cls):
        if instance is None: return self
        foo=types.MethodType(self,instance)
        print("profiled.get:",foo)
        return foo
    

    class spam:

    @profiled
    def bar(self,x):print(x)
    

    if name == 'main':

    s=spam()
    print(s.__dict__,spam.__dict__,'\n')
    f=s.bar
    print(f,type(f),f.__dict__,sep='\n')
    f("TEST")  #f 已经是绑定的方法了,为什么还要调用__call__()
    
    4 条回复    2016-12-01 22:59:40 +08:00
    explist
        1
    explist  
    OP
       2016-11-30 00:26:20 +08:00
    输出:
    {} {'__dict__': <attribute '__dict__' of 'spam' objects>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'spam' objects>, '__module__': '__main__', 'bar': <__main__.profiled object at 0x02A8BCF0>}

    profiled.get: <bound method spam.bar of <__main__.spam object at 0x70>>
    <bound method spam.bar of <__main__.spam object at 0x70>>
    <class 'method'>
    {'__annotations__': {}, '__wrapped__': <function spam.bar at 0x10>, '__qualname__': 'spam.bar', '__name__': 'bar', '__module__': '__main__', 'n': 0, '__doc__': None}
    profiled.call
    TEST
    billgreen1
        2
    billgreen1  
       2016-12-01 16:52:24 +08:00
    因为 f 不是 bar ,而是 wrappered 过的 bar,本质上应该是 profiled 类吧
    explist
        3
    explist  
    OP
       2016-12-01 22:42:56 +08:00
    看了下 MethodType 的源码,不是很明白这里面的原理:

    class _C:
    def _m(self): pass
    MethodType = type(_C()._m)
    explist
        4
    explist  
    OP
       2016-12-01 22:59:40 +08:00
    @explist
    type(_c()._m) #这是创建类还是查看类型?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1610 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:35 · PVG 00:35 · LAX 08:35 · JFK 11:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.