1
freefcw 2011-01-10 18:22:50 +08:00
- -真想说活该
为什么要搞这么麻烦呢,我对太过抽象的东西一般不用,实在是不放心,比如C的void指针 |
4
ssword 2011-01-10 21:29:12 +08:00
py的话可以lambda,ruby的话可以proc,C#有delegate,java还能拿个匿名类
什么语言呢,感觉不至于祭出来反射吧... |
7
keakon 2011-01-10 23:57:35 +08:00
try: f = getattr('funcname')
except AttributeError: ... else: f(*args) |
8
ssword 2011-01-11 20:26:44 +08:00
@ayanamist 一个“类”的函数,还是一个“对象”的方法呢?
一定要动态调用一个对象的方法的话,反射是必须的(不过鸭子类型的动态语言里的“反射”其实很模糊)。 但是仅仅是为不同的输入选择不同的行为的话,感觉还是lambda更好。比如拿个dict里面放针对不同操作的函数(参数最好一样,不然肯定自找麻烦),这样就行了: func = actions[act_name] if (func): func(*arg) |
9
ayanamist OP @ssword 你这样还要手动添加列表。我是访问一个类的实例里的方法,自动根据某字符串前面几行的情况调用方法。参数是一致的,不过方法很多,而且经常修改。(其实就是某聊天机器人……)
|
11
ssword 2011-01-11 22:03:27 +08:00
重点不是if,留意下dict和lambda的用法。
参数是一致的,不过方法很多 ---- 不理解类为什么这么设计。建议是省去这个类,直接上函数。 如果对一门语言足够了解,肯定能找到更优雅的解决方式。py不像java,高质量的代码是可以写的很短的 |
12
chloerei 2011-01-11 22:28:25 +08:00
今天在《软件随想录》看到一句话:异常处理本质是一种无形的goto。
不要太依赖异常,或者在抛出的时候塞进多些信息。 |
13
ayanamist OP @ssword 求指教,我可以把完整代码给你看。这是未来的开源项目,不过现在太不稳定,经常重构,所以暂时不适合公开。已加Gtalk
|
14
ayanamist OP @ssword 自己搜索一下,找到了这文章,似乎和你说的很像,不过只能塞入lambda表达式,我的函数代码很多,利用lambda表达式返回函数的话,还不如利用反射呢?
http://stackoverflow.com/questions/1583617/what-does-lambda-mean-in-python-and-whats-the-simplest-way-to-use-it python新人继续求指教 |
15
chuangbo 2011-01-11 23:40:04 +08:00
meta class 可以解决这个问题。类在声明的时候就会执行元类的代码,就可以收集方法了。webpy 的 auto_application 就是这么实现的
see: https://github.com/webpy/webpy/blob/master/web/application.py#L477 |
16
ayanamist OP |
17
chuangbo 2011-01-12 00:41:12 +08:00
|
19
keakon 2011-01-12 02:44:29 +08:00
回复真多,插句嘴:我认为短而直观的实现总是更为优雅。Python中提供了这个功能,如果你认为用它实现最简单,就不要怀疑地去使用它。
例如我在YUI里就用了getattr: https://bitbucket.org/keakon/yui/src/4adaf38a3581/yui.py#cl-1272 web.py也用了这种方法: https://github.com/webpy/webpy/blob/master/web/application.py#L633 否则得像webapp一样写很多if..else: http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/webapp/__init__.py?r=142#514 metaclass和decorator我一般只用来隐藏实现,让使用者无需关注其内部的实现。而现在的问题是你开放的这些接口本来就是用来调用的,不应该由被调用者强行注入调用者。 这也是我觉得用decorator来标记一个handler的不妥之处:传统的url mapping方式你可以很一目了然地知道哪些url映射到哪个handler了;而像Uliweb那样写个@expose的话,你得找到所有的handler才能确定这些映射关系,并且还得关注handler的定义顺序和import的顺序。 而这一切并没有带给你任何好处:逻辑更复杂了,阅读更困难了,维护更吃力了。 最后说下那个help的例子,你不觉得使用decorator的实现导致help函数与其他函数之间的耦合度增加了么? 明明其他函数已经开放了__doc__这个属性了,却还要强迫它们维护help函数所需的_actions列表。 如果定义一个Helper类,遍历自身的方法,用getattr取它们的__doc__,就可以少写一个函数、一个列表和多处@action。并且,如果这个类被继承了的话,扩展它的人也不需要写@action来保证help()仍能正常工作。假如你哪天觉得action这个名字不好,需要重命名时,也不需要各处去查找替换@action。 当然,这个例子如果用metaclass实现的话耦合度没有这么高。但在继承时如果不想展示子类的某几个方法,却发现子类的metaclass必须继承父类的metaclass;而如果有多重继承和多个元类则会更复杂。 虽然这种情况很极端,但你不觉得元类会把实现变得更加抽象么?回过头来想想,它本来不是个很简单的反射就直截了当能完成的事么? |
21
ssword 2011-01-12 17:05:05 +08:00
@ayanamist 见笑了,我也是python新手,只是对几个概念有耳闻而已。
楼主的情景该是猜到一些。是不是这样呢:在一个类里放很多函数,留一个函数作对外的接口,根据输入的不同分派一个不同的函数。回去想了下,使用反射也未尝不是一个好方法。要扩展,只需要往类里添加一个函数即可,比起一堆if else自是灵活的多了。 但是,这个类是不会变得很大呢。再者,用户输入那个“动态函数”名字要是Object的函数怎么办?虽不是什么大问题,估计也是会抛异常的。 前面说到lambda有点不准确,个人比较倾向于这样理解,即把可作为值传递的函数即lambda,或者说“匿名函数”。比如python允许这样 def func1(x): return x+1 f=func1 f(1) 函数是一等公民,这一来就可以方便的传递行为。而原先的类可以简单的重构一下,只保留几个简单的接口: class Dispatcher: def __init__(self): self.actions = {} def bind(self, cmd, func): self.action[cmd] = func def exec(self, cmd, *args): f = self.action[cmd] if f: f(*args) 这一来就可以把那些函数挪到类的外面,以后要扩展的话,只要额外import一个文件即可。 d = Dispacher() def hello(): # do something d.bind("hello", hello) def sayya(): # do something d.bind("sayya", sayya) ps: 其实Decorator也是python的一个函数式特征, @chuangbo 同学的方法很pythonic,也很喜欢 :) |
22
ayanamist OP @ssword @chuangbo 我还是公开一下我的情况吧。因为想了想,觉得如果脱开类,实现反而比较麻烦。
https://github.com/gh05tw01f/tweet-talk/blob/master/xmpp.py#L58 欢迎各种拍砖 |
23
ayanamist OP |
24
chuangbo 2011-01-12 21:40:36 +08:00
|
25
ayanamist OP @chuangbo 你是指把OAuth Consumer开放了,很多都这样做啊,我觉得这个没什么。这个东西我又不打算去申请白名单,用自己的和用我的都是一样的。除非我打算去申请白名单2W次,那就很重要了。而且我并不打算像TwiTalker那样搭建很多节点供人使用,打算问问kavin,如果kavin不打算用我的代码,那我就只用一个节点,想用的人自己部署吧,弄成像Dabr那样的情况。
|
26
david_lee_cn 2011-01-16 23:33:43 +08:00
|