专栏名称: 程序员大咖
为程序员提供最优质的博文、最精彩的讨论、最实用的开发资源;提供最新最全的编程学习资料:PHP、Objective-C、Java、Swift、C/C++函数库、.NET Framework类库、J2SE API等等。并不定期奉送各种福利。
目录
相关文章推荐
程序猿  ·  Python有史以来最强大的挑战者终于出现 ·  23 小时前  
程序员小灰  ·  我的第一个副业是什么? ·  4 天前  
阿里技术  ·  Cursor入门:MCP开发调用和项目实战 ·  3 天前  
稀土掘金技术社区  ·  协程中使用 ... ·  4 天前  
稀土掘金技术社区  ·  编程常用的 MCP Server,用自然语言写代码 ·  5 天前  
51好读  ›  专栏  ›  程序员大咖

听说你会Python?做几道题呗

程序员大咖  · 公众号  · 程序员  · 2018-03-31 10:24

正文

请到「今天看啥」查看全文


()

  • a . func () # Boom!

  • 如果我坚持使用类装饰器,应该如何修改?

    答案

    使用类装饰器后,在调用 func 函数的过程中其对应的 instance 并不会传递给 __call__ 方法,造成其 mehtod unbound ,那么解决方法是什么呢?描述符赛高

    1. class Timeit(object):

    2.    def __init__(self, func):

    3.        self.func = func

    4.    def __call__(self, *args, **kwargs):

    5.        print('invoking Timer')

    6.    def __get__(self, instance, owner):

    7.        return lambda *args, **kwargs: self.func(instance, *args, **kwargs)

    3. Python 调用机制

    描述

    我们知道 __call__ 方法可以用来重载圆括号调用,好的,以为问题就这么简单? Naive !

    1. class A(object):

    2.    def __call__(self):

    3.        print("invoking __call__ from A!")

    4. if __name__ == "__main__":

    5.    a = A()

    6.    a()  # output: invoking __call__ from A

    现在我们可以看到 a () 似乎等价于 a . __call__ () ,看起来很 Easy 对吧,好的,我现在想作死,又写出了如下的代码,

    1. a.__call__ = lambda: "invoking __call__ from lambda"

    2. a.__call__()

    3. # output:invoking __call__ from lambda

    4. a()

    5. # output:invoking __call__ from A!

    请大佬们解释下,为什么 a () 没有调用出 a . __call__ () (此题由 USTC 王子博前辈提出  )

    答案

    原因在于,在 Python 中,新式类( new class  )的内建特殊方法,和实例的属性字典是相互隔离的,具体可以看看 Python 官方文档对于这一情况的说明

    For new - style classes , implicit invocations of special methods are only guaranteed to work correctly if defined on an object ' s type , not in the object ' s instance dictionary. That behaviour is the reason why the following code raises an exception  ( unlike the equivalent example with old - style classes ):

    同时官方也给出了一个例子:

    1. class C(object):

    2.    pass

    3. c = C()

    4. c.__len__ = lambda: 5

    5. len(c)

    6. # Traceback (most recent call last):

    7. #  File "", line 1, in

    8. # TypeError: object of type 'C' has no len()

    回到我们的例子上来,当我们在执行 a . __call__ = lambda : " invoking __call__ from lambda " 时,的确在我们在 a . __dict__ 中新增加了一个 key 为 __call__ 的 item ,但是当我们执行 a () 时,因为涉及特殊方法的调用,因此我们的调用过程不会从 a . __dict__ 中寻找属性,而是从 tyee ( a ). __dict__ 中寻找属性。因此,就会出现如上所述的情况。

    4.描述符

    描述

    我想写一个 Exam 类,其属性 math 为 [ 0,100 ] 的整数,若赋值时不在此范围内则抛出异常,我决定用描述符来实现这个需求。

    1. class Grade(object):

    2.    def __init__(self):

    3.        self._score = 0

    4.    def __get__(self, instance, owner):

    5.        return self._score

    6.    def __set__(self, instance, value):

    7.        if 0 <= value <= 100:

    8.            self._score = value

    9.        else:

    10.            raise ValueError('grade must be between 0 and 100')

    11. class Exam(object):

    12.    math = Grade()

    13.    def __init__(self, math):

    14.        self







    请到「今天看啥」查看全文