Python论坛  - 讨论区

标题:[python-chinese] Python的可调用对象

2006年02月24日 星期五 16:24

刘鑫 march.liu at gmail.com
Fri Feb 24 16:24:53 HKT 2006

 刚刚手闲,写了篇小东西,很粗糙,大家见笑了。

__call__

Python中有一个有趣的语法,只要定义类型的时候,实现__call__函数,这个类型就成为可调用的。

换句话说,我们可以把这个类型的对象当作函数来使用,相当于重载了括号运算符。

例如,现在我们要计算重力环境下的自然落体位移。我们知道Sy=(gt**2)/2,那么,我们可以建立一个函数:

def g_dpm(t):

return (9.8*t**2)/2

我们都知道,地球表面的重力加速度约等于9.8m/s**2,这个函数实在没什么技术含量。

慢,头儿说了,我要算的是火星啊¥%#!

呃……你能说人家无理取闹么?EA的FIFA足球里,我还见过微重力模式的球场,总之,在计算机程序里,很多超现实的需求都有可能。

恩,最简单的办法当然是:

def mar_g_dpm(t):

return (3.92*t**2)/2 #火星表面的重力加速度约等于地球表面的2/5

不过,你真的能保证下次那个可爱的策划不会再设计一个金星场景?或者木星?或者该死的大魔导师行会开始出售新的魔法卷轴――重力操控?

当然,我们可以这样设计这个函数:

def g_dpm(g, t):

return (g*t**2)/2

但是g相对于t,是一个稳定得多的数量,基本上,在一次相关运算中,g可以当作常量。那么,一个可调用对象也许更适合。下面定义这样一个类型:

class g_dpm(object):

def __init__(self, g):

self.g = g

def __call__(self, t):

return (g*t**2)/2

计算地球场景的时候,我们就可以令e_dpm = g_dpm(9.8),s = e_dpm(t)
。同样的方式,可以很容易的生成其他重力环境下的自由落地公式。
Command模式和委托/事件

Command是GOF的《设计模式》中23种设计模式之一。简单来说,就是把行为对象化,这个过程在Python中是很自然的――Python
里的函数本来就是一种对象么。如果只是传递函数对象,用不着C/C++中胆战心惊的函数指针或Boost那样华丽的仿函数类型――这倒不是说Python就比
C/C++好,设计目标不同。如果需要更复杂的Command,我们就要用到回调对象了。

事件(event)是framework中常用的设计,通常来讲,事件应该满足以下的要求:

1、有默认行为,如果没有任何事件响应,至少保证事件发生时不会有错误,通常这时什么也不做。

2、允许为一个事件注册多个实现,这个倒不是必须的,但是常见的framework都实现了这一功能。

3、可以注销事件响应,这个就需要第一和第二点的支持。

4、针对不同的事件,可以传入对应的参数,通常这个功能是通过一个object *或void *之类的指针(对象引用)传入一个结构体来实现的。

在.net中为了支持这个功能,专门定制了一个特殊类型――Delegate,它对应C#的关键字delegate。在python
中么……这个东西其实很容易实现,事实上,我就在我的程序中使用了下面的代码:

class Delegate(set):

def __call__(self, *arg)

for foo in self:

foo(*arg)

简单吧,利用参数列表,我们还很容的实现了不同事件可能的参数定义要求。当然,这与通常见到的event(sender, args)
形式并不冲突。其实,更进一步的话,我们要实现并发响应也很容易:

import thread

class MTDelegate(set):

def __call__(self, *args)

for foo in sender:

thread.start_new_thread(foo, args)



 我们还可以让它返回事件响应值的一个序列:


 class FunDelegate(set):

def __call__(self, *arg)

return [foo(*arg) for foo in self]

__call__是一个简单而有趣的功能,利用它,我们可以更灵活的设计代码。当然,重载运算符(从C++
的观点来看,这里是重载了括号)总是存在一个风险――它太过有趣,所以容易被滥用。在使用之前,我们最好确认,这个功能用在这里,确实有助于我们的工作,而不是画蛇添足。


--
欢迎访问:
http://blog.csdn.net/ccat

刘鑫
March.Liu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060224/1f3271e8/attachment-0001.htm

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2006年02月24日 星期五 17:02

ajax chelsea ajaxchelsea at gmail.com
Fri Feb 24 17:02:16 HKT 2006

不错,还有没有其它有趣的函数? 这些函数的信息都是从什么文档看到的(具体一点)?

在06-2-24,刘鑫 <march.liu at gmail.com> 写道:
>
> 刚刚手闲,写了篇小东西,很粗糙,大家见笑了。
>
> __call__
>
> Python中有一个有趣的语法,只要定义类型的时候,实现__call__函数,这个类型就成为可调用的。
>
> 换句话说,我们可以把这个类型的对象当作函数来使用,相当于重载了括号运算符。
>
> 例如,现在我们要计算重力环境下的自然落体位移。我们知道Sy=(gt**2)/2,那么,我们可以建立一个函数:
>
> def g_dpm(t):
>
> return (9.8*t**2)/2
>
> 我们都知道,地球表面的重力加速度约等于9.8m/s**2,这个函数实在没什么技术含量。
>
> 慢,头儿说了,我要算的是火星啊¥%#!
>
> 呃……你能说人家无理取闹么?EA的FIFA足球里,我还见过微重力模式的球场,总之,在计算机程序里,很多超现实的需求都有可能。
>
> 恩,最简单的办法当然是:
>
> def mar_g_dpm(t):
>
> return (3.92*t**2)/2 #火星表面的重力加速度约等于地球表面的2/5
>
> 不过,你真的能保证下次那个可爱的策划不会再设计一个金星场景?或者木星?或者该死的大魔导师行会开始出售新的魔法卷轴――重力操控?
>
> 当然,我们可以这样设计这个函数:
>
> def g_dpm(g, t):
>
> return (g*t**2)/2
>
> 但是g相对于t,是一个稳定得多的数量,基本上,在一次相关运算中,g可以当作常量。那么,一个可调用对象也许更适合。下面定义这样一个类型:
>
> class g_dpm(object):
>
> def __init__(self, g):
>
> self.g = g
>
> def __call__(self, t):
>
> return (g*t**2)/2
>
> 计算地球场景的时候,我们就可以令e_dpm = g_dpm(9.8),s = e_dpm(t)
> 。同样的方式,可以很容易的生成其他重力环境下的自由落地公式。
> Command模式和委托/事件
>
> Command是GOF的《设计模式》中23种设计模式之一。简单来说,就是把行为对象化,这个过程在 Python中是很自然的――Python
> 里的函数本来就是一种对象么。如果只是传递函数对象,用不着C/C++中胆战心惊的函数指针或Boost那样华丽的仿函数类型――这倒不是说 Python
> 就比C/C++好,设计目标不同。如果需要更复杂的Command,我们就要用到回调对象了。
>
> 事件(event)是framework中常用的设计,通常来讲,事件应该满足以下的要求:
>
> 1、有默认行为,如果没有任何事件响应,至少保证事件发生时不会有错误,通常这时什么也不做。
>
> 2、允许为一个事件注册多个实现,这个倒不是必须的,但是常见的framework都实现了这一功能。
>
> 3、可以注销事件响应,这个就需要第一和第二点的支持。
>
> 4、针对不同的事件,可以传入对应的参数,通常这个功能是通过一个object *或void *之类的指针(对象引用)传入一个结构体来实现的。
>
> 在.net中为了支持这个功能,专门定制了一个特殊类型――Delegate,它对应C#的关键字 delegate。在python
> 中么……这个东西其实很容易实现,事实上,我就在我的程序中使用了下面的代码:
>
> class Delegate(set):
>
> def __call__(self, *arg)
>
> for foo in self:
>
> foo(*arg)
>
> 简单吧,利用参数列表,我们还很容的实现了不同事件可能的参数定义要求。当然,这与通常见到的event(sender, args)
> 形式并不冲突。其实,更进一步的话,我们要实现并发响应也很容易:
>
> import thread
>
> class MTDelegate(set):
>
> def __call__(self , *args)
>
> for foo in sender:
>
> thread.start_new_thread(foo, args)
>
>
>
> 我们还可以让它返回事件响应值的一个序列:
>
>
> class FunDelegate(set):
>
> def __call__(self, *arg)
>
> return [foo(*arg) for foo in self]
>
> __call__是一个简单而有趣的功能,利用它,我们可以更灵活的设计代码。当然,重载运算符(从C++的观点来看,这里是重载了括号)总是存在一个风险――它太过有趣,所以容易被滥用。在使用之前,我们最好确认,这个功能用在这里,确实有助于我们的工作,而不是画蛇添足。
>
>
>
> --
> 欢迎访问:
> http://blog.csdn.net/ccat
>
> 刘鑫
> March.Liu
>
> _______________________________________________
> python-chinese
> Post: send python-chinese at lists.python.cn
> Subscribe: send subscribe to python-chinese-request at lists.python.cn
> Unsubscribe: send unsubscribe to  python-chinese-request at lists.python.cn
> Detail Info: http://python.cn/mailman/listinfo/python-chinese
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20060224/3f4d82fc/attachment.html

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2025

    京ICP备05028076号