A generic function根据其所有参数的类型进行分派(dispatch)。程序员定义一个函数的多个实现。正确的一个是在调用时根据其参数的类型选择的。这对于对象适配等很有用。 Python 有一些通用函数,包括 len()。
这些包往往允许这样的代码:
@when(int)
def dumbexample(a):
return a * 2
@when(list)
def dumbexample(a):
return [("%s" % i) for i in a]
dumbexample(1) # calls first implementation
dumbexample([1,2,3]) # calls second implementation
我最近一直在思考的一个不那么愚蠢的例子是一个需要用户的网络组件。集成商不需要特定的 Web 框架,只需编写如下内容:
class WebComponentUserAdapter(object):
def __init__(self, guest):
self.guest = guest
def canDoSomething(self):
return guest.member_of("something_group")
@when(my.webframework.User)
componentNeedsAUser(user):
return WebComponentUserAdapter(user)
Python 有一些通用函数实现。为什么我会选择一个而不是其他的?该实现在应用程序中的使用情况如何?
我熟悉 Zope 的 zope.component.queryAdapter(object, ISomething)。程序员注册一个可调用的适配器,该适配器将特定的对象类作为其参数并返回与接口(interface)兼容的内容。这是允许插件的有用方法。与猴子修补不同,即使对象需要适应具有相同方法名称的多个接口(interface),它也能正常工作。
最佳答案
我推荐 PEAK-Rules P. Eby 的图书馆。由同一作者(虽然已弃用)是 RuleDispatch包(PEAK-Rules 的前身)。后者不再维护 IIRC。
PEAK-Rules 有很多不错的特性,其中之一就是它(嗯,不容易,但是)可扩展。除了对类型的“经典”调度之外,它还具有对任意表达式作为“监护人”的调度功能。
len() 函数不是真正的泛型函数(至少在上面提到的包的意义上,并且在某种意义上,这个术语用于像 Common Lisp 这样的语言, Dylan 或 Cecil ),因为它只是调用特殊命名(但其他常规)方法的一种方便语法:
len(s) == s.__len__()
另请注意,这只是单次分派(dispatch),也就是说,实际的接收者(上面代码中的 s)决定调用的方法实现。甚至是假设
def call_special(receiver, *args, **keys):
return receiver.__call_special__(*args, **keys)
仍然是一个单分派(dispatch)函数,因为在解析要调用的方法时只使用接收器。其余参数只是简单地传递,但它们不影响方法选择。
这与多重分派(dispatch)不同,后者没有专门的接收者,所有参数都用于找到要调用的实际方法实现。这就是真正让整个事情变得有值(value)的原因。恕我直言,如果它只是某种奇怪的语法糖,没有人会费心去使用它。
from peak.rules import abstract, when
@abstract
def serialize_object(object, target):
pass
@when(serialize_object, (MyStuff, BinaryStream))
def serialize_object(object, target):
target.writeUInt32(object.identifier)
target.writeString(object.payload)
@when(serialize_object, (MyStuff, XMLStream))
def serialize_object(object, target):
target.openElement("my-stuff")
target.writeAttribute("id", str(object.identifier))
target.writeText(object.payload)
target.closeElement()
在这个例子中,调用如下
serialize_object(MyStuff(10, "hello world"), XMLStream())
考虑两个参数以决定实际上必须调用哪个方法。
对于 Python 中通用函数的良好使用场景,我建议阅读 peak.security 的重构代码这为使用通用函数(使用 RuleDispatch)进行访问权限检查提供了一个非常优雅的解决方案。
关于python - Python 维护最好的通用函数实现是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1445065/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串