返回介绍

01. Python 工具

02. Python 基础

03. Numpy

04. Scipy

05. Python 进阶

06. Matplotlib

07. 使用其他语言进行扩展

08. 面向对象编程

09. Theano 基础

10. 有趣的第三方模块

11. 有用的工具

12. Pandas

修饰符的使用

发布于 2022-09-03 20:46:14 字数 8078 浏览 0 评论 0 收藏 0

@classmethod 修饰符

Python 标准库中,有很多自带的修饰符,例如 classmethod 将一个对象方法转换了类方法:

In [1]:

class Foo(object):
    @classmethod
    def bar(cls, x):
        print 'the input is', x

    def __init__(self):
        pass

类方法可以通过 类名.方法 来调用:

In [2]:

Foo.bar(12)
the input is 12

@property 修饰符

有时候,我们希望像 Java 一样支持 getterssetters 的方法,这时候就可以使用 property 修饰符:

In [3]:

class Foo(object):
    def __init__(self, data):
        self.data = data

    @property
    def x(self):
        return self.data

此时可以使用 .x 这个属性查看数据(不需要加上括号):

In [4]:

foo = Foo(23)
foo.x

Out[4]:

23

这样做的好处在于,这个属性是只读的:

In [5]:

foo.x = 1
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-e5e7e6c675ef> in <module>()
----> 1  foo.x = 1

AttributeError: can't set attribute

如果想让它变成可读写,可以加上一个修饰符 @x.setter

In [6]:

class Foo(object):
    def __init__(self, data):
        self.data = data

    @property
    def x(self):
        return self.data

    @x.setter
    def x(self, value):
        self.data = value

In [7]:

foo = Foo(23)
print foo.x
23

可以通过属性改变它的值:

In [8]:

foo.x = 1
print foo.x
1

Numpy 的 @vectorize 修饰符

numpyvectorize 函数讲一个函数转换为 ufunc,事实上它也是一个修饰符:

In [9]:

from numpy import vectorize, arange

@vectorize
def f(x):
    if x <= 0:
        return x
    else:
        return 0

f(arange(-10.0,10.0))

Out[9]:

array([-10.,  -9.,  -8.,  -7.,  -6.,  -5.,  -4.,  -3.,  -2.,  -1.,   0.,
         0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.])

注册一个函数

来看这样的一个例子,定义一个类:

In [10]:

class Registry(object):
    def __init__(self):
        self._data = {}
    def register(self, f, name=None):
        if name == None:
            name = f.__name__
        self._data[name] = f
        setattr(self, name, f)

register 方法接受一个函数,将这个函数名作为属性注册到对象中。

产生该类的一个对象:

In [11]:

registry = Registry()

使用该对象的 register 方法作为修饰符:

In [12]:

@registry.register
def greeting():
    print "hello world"

这样这个函数就被注册到 registry 这个对象中去了:

In [13]:

registry._data

Out[13]:

{'greeting': <function __main__.greeting>}

In [14]:

registry.greeting

Out[14]:

<function __main__.greeting>

flask ,一个常用的网络应用,处理 url 的机制跟这个类似。

使用 @wraps

一个通常的问题在于:

In [15]:

def logging_call(f):
    def wrapper(*a, **kw):
        print 'calling {}'.format(f.__name__)
        return f(*a, **kw)
    return wrapper

@logging_call
def square(x):
    '''
 square function.
 '''
    return x ** 2

print square.__doc__, square.__name__
None wrapper

我们使用修饰符之后,squaremetadata 完全丢失了,返回的函数名与函数的 docstring 都不对。

一个解决的方法是从 functools 模块导入 wraps 修饰符来修饰我们的修饰符:

In [16]:

import functools

def logging_call(f):
    @functools.wraps(f)
    def wrapper(*a, **kw):
        print 'calling {}'.format(f.__name__)
        return f(*a, **kw)
    return wrapper

@logging_call
def square(x):
    '''
 square function.
 '''
    return x ** 2

print square.__doc__, square.__name__
    square function.
     square

现在这个问题解决了,所以在自定义修饰符方法的时候为了避免出现不必要的麻烦,尽量使用 wraps 来修饰修饰符!

Class 修饰符

与函数修饰符类似,类修饰符是这样一类函数,接受一个类作为参数,通常返回一个新的类。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文