http://blog.csdn.net/pipisorry/article/details/50444769

描述器(Descriptors)

描述器决定了对象属性是如何被访问的。描述器的作用是定制当你想引用一个属性时所发生的操作。

构建描述器的方法是至少定义以下三个方法中的一个。需要注意,下文中的instance是包含被访问属性的对象实例,而owner则是被描述器修辞的类。

  • __get__(self, instance, owner) – 这个方法是当属性被通过(value = obj.attr)的方式获取时调用,这个方法的返回值将被赋给请求此属性值的代码部分。
  • __set__(self, instance, value) – 这个方法是当希望设置属性的值(obj.attr = ‘value’)时被调用,该方法不会返回任何值。
  • __delete__(self, instance) – 当从一个对象中删除一个属性时(del obj.attr),调用此方法。

译者注:对于instance和owner的理解,考虑以下代码:

classCelsius(object):
    def__init__(self, value=0.0):
        self.value=float(value)
    def__get__(self, instance, owner):
        returnself.value
    def__set__(self, instance, value):
        self.value=float(value)
 
classTemperature(object):
    celsius=Celsius()
 
temp=Temperature()
temp.celsius#calls Celsius.__get__

上例中,instance指的是temp,而owner则是Temperature。

LazyLoading Properties例子:

importweakref
 
classlazyattribute(object):
    def__init__(self, f):
        self.data=weakref.WeakKeyDictionary()
        self.f=f
    def__get__(self, obj, cls):
        ifobjnotinself.data:
            self.data[obj]=self.f(obj)
        returnself.data[obj]
 
classFoo(object):
    @lazyattribute
    defbar(self):
        print"Being lazy"
        return42
 
f=Foo()
 
printf.bar
# Being lazy
# 42
 
printf.bar
# 42

描述器很好的总结了Python中的绑定方法(bound method)这个概念,绑定方法是经典类(classic classes)的实现核心。在经典类中,当在一个对象实例的字典中没有找到某个属性时,会继续到类的字典中查找,然后再到基类的字典中,就这么一直递归的查找下去。如果在类字典中找到这个属性,解释器会检查找到的对象是不是一个Python函数对象。如果是,则返回的并不是这个对象本身,而是返回一个柯里化(currying function)的包装器对象。当调用这个包装器时,它会首先在参数列表之前插入实例,然后再调用原函数。

译者注:
1. 柯里化 – http://zh.wikipedia.org/wiki/%E6%9F%AF%E9%87%8C%E5%8C%96
2. function,method,bound method及unbound method的区别。首先,函数(function)是由def或lambda创建的。当一个函数在class语句块中定义或是由type来创建时,它会转成一个非绑定方法(unbound method),而当通过类实例(instance)来访问此方法的时候,它将转成绑定方法(bound method),绑定方法会自动将实例作为第一个参数传入方法。综上所述,方法是出现在类中的函数,绑定方法是一个绑定了具体实例的方法,反之则是非绑定方法。

综上,描述器被赋值给类,而这些特殊的方法就在属性被访问的时候根据具体的访问类型自动地调用。

[Descriptor Protocol]

皮皮blog

元类(MetaClasses)

元类提供了一个改变Python类行为的有效方式。

元类的定义是“一个类的类”。任何实例是它自己的类都是元类。

classdemo(object):
    pass
 
obj=demo()
 
print"Class of obj is {0}".format(obj.__class__)
print"Class of obj is {0}".format(demo.__class__)
 
# Class of obj is <class '__main__.demo'>
# Class of obj is <type 'type'>

在上例中,我们定义了一个类demo,并且生成了一个该类的对象obj。首先,可以看到obj的__class__是demo。有意思的来了,那么demo的class又是什么呢?可以看到demo的__class__是type。

所以说type是python类的类,换句话说,上例中的obj是一个demo的对象,而demo本身又是type的一个对象。

所以说type就是一个元类,而且是python中最常见的元类,因为它使python中所有类的默认元类。

因为元类是类的类,所以它被用来创建类(正如类是被用来创建对象的一样)。但是,难道我们不是通过一个标准的类定义来创建类的么?的确是这样,但是python内部的运作机制如下:

    • 当看见一个类定义,python会收集所有属性到一个字典中。
    • 当类定义结束,python将决定类的元类,我们就称它为Meta吧。
    • 最后,python执行Meta(name, bases, dct),其中:

a. Meta是元类,所以这个调用是实例化它。
b. name是新建类的类名。
c. bases是新建类的基类元组
d. dct将属性名映射到对象,列出所有的类属性。

那么如何确定一个类(A)的元类呢?简单来说,如果一个类(A)自身或其基类(Base_A)之一有__metaclass__属性存在,则这个类(A/Base_A)就是类(A)的元类。否则type就将是类(A)的元类。[Python高级编程技巧]

皮皮blog

__slots__

默认情况下,Python 用一个字典来保存一个对象的实例属性。这使得我们可以在运行的时候动态的给类的实例添加新的属性:
test = Test()
test.new_key = 'new_value'
然而这个字典浪费了多余的空间 — 很多时候我们不会创建那么多的属性。因此通过__slots__可以告诉 Python 不要使用字典而是固定集合来分配空间。
class Test(object):
    # 用列表罗列所有的属性
    __slots__ = ['name', 'value']
    def __init__(self, name='test', value='0'):
        self.name = name
        self.value = value

test = Test()
# 此时再增加新的属性则会报错
test.new_key = 'new_value'
# AttributeError: 'Test' object has no attribute 'new_key'

__call__

通过定义类中的__call__方法,可以使该类的实例能够像普通函数一样调用。
class AddNumber(object):
    def __init__(self):
        self.num = 0

    def __call__(self, num=1):
        self.num += num

add_number = AddNumber()
print(add_number.num) # 0
add_number() # 像方法一样的调用
print(add_number.num) # 1
add_number(3)
print(add_number.num) # 4
通过这种方式实现的好处是,可以通过类的属性来保存状态,而不必创建一个闭包或者全局变量。

from:http://blog.csdn.net/pipisorry/article/details/50444769

ref:Python “黑魔法” 之 Meta Classes

[Special method names]

python类:描述器Descriptors和元类MetaClasses的更多相关文章

  1. python面向对象(六)之元类

    元类 1. 类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍然成立: In [13]: class ObjectCreator(object): . ...

  2. python中对象、类型和元类之间的关系

    在python中对象.类型和元类构成了一个微妙的世界. 他们有在这个世界里和平共处,相辅相成.它们遵循着几条亘古不变的定律: 1.python中无处不对象 2.所有对象都有三种特性:id.类型.值 3 ...

  3. python面向对象反射-框架原理-动态导入-元类-自定义类-单例模式-项目的生命周期-05

    反射 reflect 反射(reflect)其实是反省,自省的意思 反省:指的是一个对象应该具备可以检测.修改.增加自身属性的能力 反射:通过字符串获取对象或者类的属性,进行操作 设计框架时需要通过反 ...

  4. Python中对象、类型、元类之间的关系

    Python里的对象.类型和元类的关系很微妙也很有意思. 1989年圣诞节期间,上帝很无聊,于是创造了一个世界. 对象 在这个世界的运转有几条定律. 1.一切都是对象 对象(object)是这个世界的 ...

  5. Python 黑魔法 --- 描述器(descriptor)

    Python 黑魔法---描述器(descriptor) Python黑魔法,前面已经介绍了两个魔法,装饰器和迭代器,通常还有个生成器.生成器固然也是一个很优雅的魔法.生成器更像是函数的行为.而连接类 ...

  6. Python之描述器

    1.描述器的表现 用到三个魔术方法,__get__(), __set__(), __delete__() 方法签名如下 object.__get__(self,instance,owner) obje ...

  7. 《Effective Python》笔记——第4章 元类及属性

    一.用属性取代get和set方法 常规的get和set方法如下: class OldResistor(): def __init__(self, ohms): self.__ohms = ohms d ...

  8. Python语言特性之2:元类

    问题:Python中的元类(metaclasses)是什么?一般使用它干什么? 原地址:http://stackoverflow.com/questions/100003/what-is-a-meta ...

  9. Java类载入器(二)——自己定义类载入器

      用户定制自己的ClassLoader能够实现以下的一些应用: 自己定义路径下查找自己定义的class类文件,或许我们须要的class文件并不总是在已经设置好的Classpath以下,那么我们必须想 ...

随机推荐

  1. GNS3 1.4.0b3 MSTP多生成树配置实验

    一.实验目标 掌握MSTP多生成树配置,VLAN配置,trunk配置,etherchannel配置 二.实验平台 系统:WIN7以上windows,X64版本.CPU支持虚拟化,并在BIOS中开启虚拟 ...

  2. 开发一个 app 有多难?

    171 个回答 默认排序​ 道衍天机 有事情的加微信1293190838找我 1,150 人赞同了该回答 ----------------------------------------------- ...

  3. jvm(四):垃圾回收

    垃圾回收我们主要从以下三个方面进行描述 垃圾对象的判断 目前判断对象为垃圾对象有两种方法:引用计数法,可达性分析法,目前普遍是的是可达性分析法 可达性分析法的实现原理: 定义gcroot一直往下找,如 ...

  4. Spring-cloud(六) Hystrix入门

    前提 一个可用的Eureka注册中心(文中以之前博客中双节点注册中心,不重要) 一个连接到这个注册中心的服务提供者 快速入门 项目搭建 搭建一个新maven项目,artifactid为Ribbon-c ...

  5. Python中将一个对象倒序输出的4种方法

    Python中将一个对象倒序输出的4种方法就用列表来举例说明吧: >>> lst = [1,2,3,4,5,6] #创建测试列表 #方法1: >>> lst.rev ...

  6. DB2 911错误的解释

    SQL0911N  因为死锁或超时,所以当前事务已回滚.原因码为 "<原因码>". 说明: 当前工作单元参与了未解决的对象争用,因此必须回滚. 原因码如下所示: 2   ...

  7. Mac OS: How to keep network connection alive after sleep

    Do the following: Find out what the network interface is for your wifi. Mine is "en1" for ...

  8. iOS 中隐藏UITableView最后一条分隔线

    如何优雅的隐藏UITableView中最后一条分割线? 这个问题是很常见,却又不太容易解决的. 可能通常的做法都是隐藏UITableView的分割线,自定义一条. 最近在使用弹出菜单的时候,同样遇到了 ...

  9. 《Shazam It! Music Recognition Algorithms, Fingerprinting, and Processing》译文

    最近看到一篇老外写的博客,简单介绍了shazam的工作原理.图非常好,所以就把它翻译成中文,希望对搞听歌识曲的人有帮助. 你可能遇到这样的场景:在酒吧或者餐厅听到你非常熟悉的歌,也许你曾经听过无数次, ...

  10. YCSB性能测试工具使用

    在网上查In-Memory NoSQL性能测试的资料时,偶然间发现了这个性能测试工具YCSB,全称为"Yahoo! Cloud Serving Benchmark".它内置了对常见 ...