`
marlonyao
  • 浏览: 252813 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

探索Python下的property, classmethod, staticmethod的实现

阅读更多
Python有几个内置方法poperty, classmethod, staticmethod,其中property用来将方法变成属性,而classmethod将一个类的函数变成类方法,staticmethod将类的一个函数变成静态方法。它们是如何使用的,我这里就不讲了,只讲它们可能是怎样实现的。之所以说“可能”,是因为我并不确定,我对Python也只是初学,并且这里讲的可能也只是其中一种实现方式而已。

在讲实现之前我需要稍微介绍一下Python中的Descriptor,Descriptor提供了一种强大的机制来实现对属性的自定义访问。我建议大家都看下Shalabh Chaturvedi的这篇文章,我这篇博客不过是补充它只是简单提到的东西而已,甚至例子也大部分来源于那篇文章。

下面是一个Descriptor的例子(该例子来源于Shalabh Chaturvedi的文章):
class Desc(object):
    def __get__(self, obj, cls=None):
        print '__get__: %s' % ((self, obj, cls),)

    def __set__(self, obj, val):
        print '__set__: %s' % ((self, obj, val),)

    def __delete__(self, obj):
        print '__delete__: %s' % ((self, obj), )

class C(object):
    d = Desc()

cobj = C()
x = cobj.d
cobj.d = 'setting a value'
cobj.__dict__['d'] = 'try to force a value'
x = cobj.d
del cobj.d

x = C.d
C.d = 'setting a value on class'

上面的代码输出:
__get__: (<__main__.Desc object at 0xb74b33cc>, <__main__.C object at 0xb74b342c>, <class '__main__.C'>)
__set__: (<__main__.Desc object at 0xb74b33cc>, <__main__.C object at 0xb74b342c>, 'setting a value')
__get__: (<__main__.Desc object at 0xb74b33cc>, <__main__.C object at 0xb74b342c>, <class '__main__.C'>)
__delete__: (<__main__.Desc object at 0xb74b33cc>, <__main__.C object at 0xb74b342c>)
__get__: (<__main__.Desc object at 0xb74b33cc>, None, <class '__main__.C'>)

我不想作太多解释,只需要注意访问和给cobj.d赋值调用的是Desc的__get__和__set__方法,即使通过__dict__来覆盖cobj的d属性时也是如此。(需要注意的是:Descriptor分为Data Descriptor和Non-Data Descriptor,区别在于Data Descriptor同时实现__get__和__set__方法,而Non-Data只实现了__get__方法,两者的行为不同,上面的例子是Data Descriptor)。

接下来,我们来看如何利用Descriptor来实现Python内置classmethod方法所提供的功能。为了和内置classmethod区别,我将它命名为myclassmethod,它的实现如下:
def myclassmethod(clsmethod):
    return ClassMethodDesc(clsmethod)

class ClassMethodDesc(object):
    def __init__(self, clsmethod):
        self.clsmethod = clsmethod

    def __get__(self, obj, cls=None):
        def wrap(*args, **kwargs):
            return self.clsmethod(cls, *args, **kwargs)
        return wrap

myclassmethod返回ClassMethodDesc,它是一个Non-Data Descriptor,只实现了__get__方法,它会返回一个函数,调用这个函数时,它会将调用委托给clsmethod,但第一个参数设置成会传递一个cls参数。它的使用方式和内置的classmethod实现一样,下面是个例子:
class ClassMethodDemo(object):
    def cls_method(cls):
        print 'You called class %s' % cls

    cls_method = myclassmethod(cls_method)

if __name__ == '__main__':
    obj = ClassMethodDemo()
    obj.cls_method()

    ClassMethodDemo.cls_method()

上面代码输出:
You called class <class '__main__.ClassMethodDemo'>
You called class <class '__main__.ClassMethodDemo'>


实现static方法同样很简单,这里就不写了。下面的myproperty方法实现和内置property基本一样的功能,只是它的参数都是必需的,并且只接受getmethod和setmethod两个方法,不再作解释.
def myproperty(getmethod, setmethod):
    return PropertyMethodDesc(getmethod, setmethod)

class PropertyMethodDesc(object):
    def __init__(self, getmethod, setmethod):
        self.getmethod = getmethod
        self.setmethod = setmethod

    def __get__(self, obj, cls=None):
        return self.getmethod(obj)

    def __set__(self, obj, val):
        return self.setmethod(obj, val)

class PropertyDemo(object):
    def get_a(self):
        print 'get_a invoked'
        return self.__dict__['a']
    def set_a(self, val):
        print 'set_a as %s' % val
        self.__dict__['a'] = val

    a = myproperty(get_a, set_a)

if __name__ == '__main__':
    obj = PropertyDemo()
    obj.a = 5
    print obj.a


分享到:
评论

相关推荐

    Python库 | simple_classproperty-1.3.1-py3-none-any.whl

    `classproperty`与`classmethod`和`staticmethod`的主要区别在于,`classmethod`接收的第一个参数是类本身,而`staticmethod`则不接收任何特殊参数,两者都处理方法,而非属性。`classproperty`则提供了属性的类...

    python函数文档_python函数_python文档_python_

    例如,`@staticmethod` 和 `@classmethod` 装饰器改变类方法的调用方式,`@property` 用于创建属性访问器。 Python 标准库还包含了异常处理机制,使用 `try/except` 语句捕获和处理错误。例如: ```python try: ...

    python基于property()函数定义属性

    Python还提供了`@property`、`@classmethod`、`@staticmethod` 等装饰器,分别用于创建getter、定义类方法和静态方法。这些装饰器使得类的方法和属性更具面向对象特性,提高了代码的可复用性和可扩展性。 总之,`...

    python实现装饰器、描述符

    装饰器进阶:property、staticmethod、classmethod源码分析(python代码实现) 装饰器基础 无参装饰器 ''' 假定有一个需求是:打印程序函数运行顺序 此案例打印的结果为: foo1 function is starting foo2 ...

    Python经典面试题集锦 Python练习题 Python考试题目整理汇总 共18页.pdf

    5. **特性(property)**:在Python中,property是用于封装类的属性,它将数据访问逻辑包装在getter和setter方法中,以提供数据验证和控制。通过使用`@property`、`@name.setter`等装饰器可以创建特性。 6. **使用...

    python对象模型

    描述符可以控制对属性的访问,并且被用来实现Python的@property装饰器、@classmethod、@staticmethod和__slots__等特性。 属性查找(Attribute Lookup):属性查找是Python处理实例和类属性访问的过程。当查找实例x...

    Python 3.6.5 Doc

    1. 装饰器:用于扩展或修改函数、类的功能,如 @classmethod、@staticmethod、@property 等。 2. 上下文管理器:通过 with 语句进行资源的自动获取和释放,如文件操作。 3. 面向切面编程(AOP):利用装饰器实现切面...

    python面向对象下载

    此外,Python的标准库提供了许多内置的面向对象工具,比如`__slots__`用于节省内存,`property`用于创建属性的访问器,以及`@classmethod`和`@staticmethod`用于定义类方法和静态方法。这些都是在实际开发中会经常...

    python面试题

    下面这些是什么意思:`@classmethod`,`@staticmethod`,`@property`? - **`@classmethod`**: 类方法,第一个参数通常为类本身(`cls`)。 - **`@staticmethod`**: 静态方法,没有额外的参数。 - **`@property`**: ...

    Python 的描述符 descriptor详解

    问题,另外还引入了一些新的概念,比如 classmethod, staticmethod, super, Property 等。因此理解 descriptor 有助于更好地了解 Python 的运行机制。 那么什么是 descriptor 呢? 简而言之:descriptor 就是一类...

    python面向对象 自己手写的

    ### Python面向对象编程详解 #### 一、创建类和对象 面向对象编程(Object-Oriented Programming, OOP)是一种程序设计思想,它把对象作为程序的基本单元,一个对象包含了数据和对这些数据的操作方法。在Python中,...

    python中访问限制共3页.pdf.zip

    Python的`staticmethod`和`classmethod`装饰器允许我们在不绑定实例或类的情况下调用方法,这在访问控制中有时也会发挥作用,特别是在设计模式如工厂方法中。 8. 私有变量的访问: 尽管Python没有硬性的私有变量...

    python速查表.zip

    使用`@decorator`语法,如`@staticmethod`、`@classmethod`、`@property`等。 11. **上下文管理器**:使用`with`语句可以确保资源的正确释放,如打开文件后自动关闭。 12. **多线程与多进程**:Python的`threading...

    Python_基础面试题.pdf

    Python中的内置装饰器包括@classmethod、@staticmethod和@property。@classmethod用于类方法,它接收类对象作为第一个参数;@staticmethod不接收类或实例作为参数,用于定义与类相关的功能;@property用于属性的获取...

    python 源码剖析

    深入理解`@staticmethod`、`@classmethod`和`@property`等内置装饰器的源码,有助于我们编写自己的高效装饰器。 Python的标准库提供了大量预先封装好的功能,如网络通信、文件操作、数据结构等。通过查看标准库的...

    一文详述 Python 中的 property 语法

    `property`可以配合`@classmethod`和`@staticmethod`装饰器一起使用,实现对属性的获取和设置操作。例如: ```python class Money: def __init__(self): self.__money = 0 @property def money(self): ...

    python全套课程继承与多态

    同时,你还可以使用Python的`@property`装饰器来创建只读属性,或者提供额外的检查和控制。 **类的常见属性**包括实例变量(通过`self`在`__init__`中初始化)、类变量(属于类而非实例,所有实例共享同一份数据)...

    Python知识点.doc

    通过`@classmethod`和`@staticmethod`,类装饰器可以处理类对象和实例对象。 13. 内存管理机制:Python采用垃圾回收机制自动管理内存,当一个对象没有引用时,垃圾回收器会将其释放。此外,Python还有引用计数和分...

    python 装饰器(示例)

    Python还提供了一些内置的装饰器,例如`@staticmethod`和`@classmethod`,它们分别用于定义静态方法和类方法。此外,`@property`装饰器用于将一个方法转化为属性,提供访问控制和计算属性的功能。 装饰器还可以层层...

Global site tag (gtag.js) - Google Analytics