zoukankan      html  css  js  c++  java
  • 子类化内置类型

    Python 2.2之后内置类型开始可以子类化了

    但是,CPython中的内置类型不会调用用户重写的类的特殊方法。

    PyPy的文档中描述了这个问题。subclasses-of-built-in-types

    正式情况下,CPython 并没有官方规定内置类型的子类中重写的方法是否会被隐式调用。
    
    基本上,这些用户重写的方法不会被同一对象的其他内置方法调用。
    
    例如,在dict的子类中重写的 `__getitem__()` 方法不会被内置的 `get()` 方法调用。
    
    以上情况在CPython和PyPy中都是一致的。
    
    在内置函数或方法是否会调用另一个对象的重写方法而不是self上,两者会出现差异。
    
    PyPy经常会在Cpython不调用的情况下调用。
    

    两个例子:

    ex1:

    class D(dict):
        def __getitem__(self, key):
            return "%r from D" % (key,)
    
    class A(object):
        pass
    
    a = A()
    a.__dict__ = D()
    a.foo = "a's own foo"
    print a.foo
    # CPython => a's own foo
    # PyPy => 'foo' from D
    

    ex2:

    glob = D(foo="base item")
    loc = {}
    exec "print foo" in glob, loc
    # CPython => base item
    # PyPy => 'foo' from D
    

    原生类型的这种行为违背了面向对象编程的一个基本原则:始终应该从实例(self)所属的类开始搜索方法,即使在超类实现的类中调用也是如此。(不过 __missing__ 方法是个特例。)

    在CPython的实现结构中,内建方法大部分会忽略用户重写的特殊方法,所以产生了UserDict,UserString,UserList来解决这个问题。

    In : class NewDict(dict):
    ...:     def __getitem__(self, key):
    ...:         return 42
    ...:     
    In : d = NewDict(a=1)
    In : d
    Out: {'a': 42}
    In : d2 = {}
    In : d2.update(d)       #CPython中的update会忽略NewDict中的__getitem__方法
    In : d2
    Out: {'a': 1}
    

    因此用户如果自己定义的类应该继承collections模块中的类。而不是子类化内置类。

    *《流畅的Python》 12.1

  • 相关阅读:
    Raid5 Raid10性能测试
    MetaData_model_package
    UBoot命令说明
    ubuntu 12.10 配置一个Apache+MySQL+phpMyAdmin环境
    SSH服务器
    VC2008使用boost库方式
    嵌入式Web服务器BOA移植
    利用matlab将数据写入指定列的方法
    error LNK2019: 无法解析的外部符号,解决办法
    在CYGWIN下编译和运行软件Bundler ,以及PMVS,CMVS的编译与使用
  • 原文地址:https://www.cnblogs.com/leisurelylicht/p/zi-lei-hua-nei-zhi-lei-xing-subclassesofbuiltintyp.html
Copyright © 2011-2022 走看看